Fix data race in wxGetTimeZone()
We could return a wrong value from this function if two threads called it simultaneously, as gmtoffset value could be returned without DST adjustment in one of them. And just accessing it from two different threads without synchronization was a data race on its own. Fix both problems by using an atomic int for it and taking care to only set it to the correct value.
This commit is contained in:
parent
dd8935b07d
commit
b3ff1f3e61
1 changed files with 10 additions and 7 deletions
|
|
@ -37,6 +37,10 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WX_GMTOFF_IN_TM
|
||||
#include <atomic>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
|
||||
wxDECL_FOR_STRICT_MINGW32(void, tzset, (void));
|
||||
|
|
@ -119,12 +123,10 @@ struct tm *wxGmtime_r(const time_t* ticks, struct tm* temp)
|
|||
int wxGetTimeZone()
|
||||
{
|
||||
#ifdef WX_GMTOFF_IN_TM
|
||||
// set to true when the timezone is set
|
||||
static bool s_timezoneSet = false;
|
||||
static long gmtoffset = LONG_MAX; // invalid timezone
|
||||
static std::atomic<int> s_gmtoffset{INT_MAX}; // invalid timezone
|
||||
|
||||
// ensure that the timezone variable is set by calling wxLocaltime_r
|
||||
if ( !s_timezoneSet )
|
||||
if ( s_gmtoffset == INT_MAX )
|
||||
{
|
||||
// just call wxLocaltime_r() instead of figuring out whether this
|
||||
// system supports tzset(), _tzset() or something else
|
||||
|
|
@ -132,20 +134,21 @@ int wxGetTimeZone()
|
|||
struct tm tm;
|
||||
|
||||
wxLocaltime_r(&t, &tm);
|
||||
s_timezoneSet = true;
|
||||
|
||||
// note that GMT offset is the opposite of time zone and so to return
|
||||
// consistent results in both WX_GMTOFF_IN_TM and !WX_GMTOFF_IN_TM
|
||||
// cases we have to negate it
|
||||
gmtoffset = -tm.tm_gmtoff;
|
||||
int gmtoffset = static_cast<int>(-tm.tm_gmtoff);
|
||||
|
||||
// this function is supposed to return the same value whether DST is
|
||||
// enabled or not, so we need to use an additional offset if DST is on
|
||||
// as tm_gmtoff already does include it
|
||||
if ( tm.tm_isdst )
|
||||
gmtoffset += 3600;
|
||||
|
||||
s_gmtoffset = gmtoffset;
|
||||
}
|
||||
return (int)gmtoffset;
|
||||
return s_gmtoffset;
|
||||
#elif defined(__WINE__)
|
||||
struct timeb tb;
|
||||
ftime(&tb);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue