88#include "pycore_time.h" // _PyTimeFraction
99
1010#include <time.h> // clock()
11+ #include <string.h> // strncpy()
12+
13+ static PyMutex timezone_mutex = {0 };
1114#ifdef HAVE_SYS_TIMES_H
1215# include <sys/times.h> // times()
1316#endif
@@ -567,6 +570,21 @@ GMT). When 'seconds' is not passed in, convert the current time instead.\n\
567570If the platform supports the tm_gmtoff and tm_zone, they are available as\n\
568571attributes only." );
569572
573+ #ifdef HAVE_STRUCT_TM_TM_ZONE
574+ static void
575+ snapshot_tm_zone (struct tm * p , char * buf , size_t n )
576+ {
577+ if (p -> tm_zone != NULL ) {
578+ strncpy (buf , p -> tm_zone , n - 1 );
579+ buf [n - 1 ] = '\0' ;
580+ }
581+ else {
582+ buf [0 ] = '\0' ;
583+ }
584+ p -> tm_zone = buf ;
585+ }
586+ #endif
587+
570588static PyObject *
571589time_localtime (PyObject * module , PyObject * args )
572590{
@@ -575,11 +593,18 @@ time_localtime(PyObject *module, PyObject *args)
575593
576594 if (!parse_time_t_args (args , "|O:localtime" , & when ))
577595 return NULL ;
578- if (_PyTime_localtime (when , & buf ) != 0 )
596+
597+ PyMutex_Lock (& timezone_mutex );
598+ if (_PyTime_localtime (when , & buf ) != 0 ) {
599+ PyMutex_Unlock (& timezone_mutex );
579600 return NULL ;
601+ }
580602
581603 time_module_state * state = get_time_state (module );
582604#ifdef HAVE_STRUCT_TM_TM_ZONE
605+ char zone_buf [64 ];
606+ snapshot_tm_zone (& buf , zone_buf , sizeof (zone_buf ));
607+ PyMutex_Unlock (& timezone_mutex );
583608 return tmtotuple (state , & buf );
584609#else
585610 {
@@ -588,6 +613,7 @@ time_localtime(PyObject *module, PyObject *args)
588613 time_t gmtoff ;
589614 strftime (zone , sizeof (zone ), "%Z" , & buf );
590615 gmtoff = timegm (& buf ) - when ;
616+ PyMutex_Unlock (& timezone_mutex );
591617 return tmtotuple (state , & local , zone , gmtoff );
592618 }
593619#endif
@@ -884,8 +910,12 @@ time_strftime(PyObject *module, PyObject *args)
884910 time_module_state * state = get_time_state (module );
885911 if (tup == NULL ) {
886912 time_t tt = time (NULL );
887- if (_PyTime_localtime (tt , & buf ) != 0 )
913+ PyMutex_Lock (& timezone_mutex );
914+ if (_PyTime_localtime (tt , & buf ) != 0 ) {
915+ PyMutex_Unlock (& timezone_mutex );
888916 return NULL ;
917+ }
918+ PyMutex_Unlock (& timezone_mutex );
889919 }
890920 else if (!gettmarg (state , tup , & buf ,
891921 "iiiiiiiii;strftime(): illegal time tuple argument" ) ||
@@ -941,8 +971,10 @@ time_strftime(PyObject *module, PyObject *args)
941971 }
942972 if (fmtlen ) {
943973 format [fmtlen ] = 0 ;
974+ PyMutex_Lock (& timezone_mutex );
944975 PyObject * unicode = time_strftime1 (& outbuf , & bufsize ,
945976 format , fmtlen , & buf );
977+ PyMutex_Unlock (& timezone_mutex );
946978 if (unicode == NULL ) {
947979 goto error ;
948980 }
@@ -1043,8 +1075,12 @@ time_asctime(PyObject *module, PyObject *args)
10431075 time_module_state * state = get_time_state (module );
10441076 if (tup == NULL ) {
10451077 time_t tt = time (NULL );
1046- if (_PyTime_localtime (tt , & buf ) != 0 )
1078+ PyMutex_Lock (& timezone_mutex );
1079+ if (_PyTime_localtime (tt , & buf ) != 0 ) {
1080+ PyMutex_Unlock (& timezone_mutex );
10471081 return NULL ;
1082+ }
1083+ PyMutex_Unlock (& timezone_mutex );
10481084 }
10491085 else if (!gettmarg (state , tup , & buf ,
10501086 "iiiiiiiii;asctime(): illegal time tuple argument" ) ||
@@ -1069,8 +1105,12 @@ time_ctime(PyObject *self, PyObject *args)
10691105 struct tm buf ;
10701106 if (!parse_time_t_args (args , "|O:ctime" , & tt ))
10711107 return NULL ;
1072- if (_PyTime_localtime (tt , & buf ) != 0 )
1108+ PyMutex_Lock (& timezone_mutex );
1109+ if (_PyTime_localtime (tt , & buf ) != 0 ) {
1110+ PyMutex_Unlock (& timezone_mutex );
10731111 return NULL ;
1112+ }
1113+ PyMutex_Unlock (& timezone_mutex );
10741114 return _asctime (& buf );
10751115}
10761116
@@ -1174,15 +1214,18 @@ time_tzset(PyObject *self, PyObject *unused)
11741214 return NULL ;
11751215 }
11761216
1217+ PyMutex_Lock (& timezone_mutex );
11771218#if !defined(MS_WINDOWS ) || defined(MS_WINDOWS_DESKTOP ) || defined(MS_WINDOWS_SYSTEM )
11781219 tzset ();
11791220#endif
11801221
11811222 /* Reset timezone, altzone, daylight and tzname */
11821223 if (init_timezone (m ) < 0 ) {
1224+ PyMutex_Unlock (& timezone_mutex );
11831225 Py_DECREF (m );
11841226 return NULL ;
11851227 }
1228+ PyMutex_Unlock (& timezone_mutex );
11861229 Py_DECREF (m );
11871230 if (PyErr_Occurred ())
11881231 return NULL ;
0 commit comments