pocoproject / poco

The POCO C++ Libraries are powerful cross-platform C++ libraries for building network- and internet-based applications that run on desktop, server, mobile, IoT, and embedded systems.
https://pocoproject.org
Other
8.32k stars 2.15k forks source link

LocalDateTime determineTzd #3145

Closed micheleselea closed 11 months ago

micheleselea commented 3 years ago

Hi all, I have an issue when I construct a LocalDateTime, because the constructor invoke determineTzd(true) the adjust=true variable make the code call for std::tm* broken = std::localtime(&epochTime); sometimes, and I really never understand why and when, the broken is null so an exception is thrown throw Poco::SystemException("cannot get local time"); This kind of behavior came from a very long time....I don't know if you ever happen to you, and how can you solve it

Mironenko commented 3 years ago

Did you check the errno? Tried to log epochTime, did you?

micheleselea commented 3 years ago

No I didn't because it's some kind of tricky error, because is not happen so frequently, and it's inside the LocalDateTime class, so usually a subsequent call to that function works

micheleselea commented 3 years ago

It's seems to me some "locked" structure or some kind of concurrent access

Mironenko commented 3 years ago

It's seems to me some "locked" structure or some kind of concurrent access

Indeed, localtime is not threadsafe. Maybe it should be replaced with localtime_r on supported platforms and protected with a dedicated mutex on the rest?

github-actions[bot] commented 2 years ago

This issue is stale because it has been open for 365 days with no activity.

aleks-f commented 2 years ago

I'l kick this can down the road, because I have no idea what to do with it - can't reproduce it, and windows seems to have a standard C function with reversed order of arguments?

micheleselea commented 2 years ago

@aleks-f exactly windows has a reverse order like that:

void LocalDateTime::determineTzd(bool adjust)
{
    if (adjust)
    {
        std::time_t epochTime = _dateTime.timestamp().epochTime();
#if defined(_WIN32) || defined(POCO_NO_POSIX_TSF)
#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
        std::tm* broken = wceex_localtime(&epochTime);
#else
        std::tm brokenBuf;
        std::tm* broken = &brokenBuf;
        errno_t err = localtime_s(broken, &epochTime);
        if (err) broken = nullptr;
#endif
        if (!broken) throw Poco::SystemException("cannot get local time");
        _tzd = Timezone::utcOffset() + Timezone::dst(_dateTime.timestamp());
#else
        std::tm broken;
#if defined(POCO_VXWORKS) && (defined(_VXWORKS_COMPATIBILITY_MODE) || (defined(_WRS_VXWORKS_MAJOR) && ((_WRS_VXWORKS_MAJOR < 6) || ((_WRS_VXWORKS_MAJOR == 6)  && (_WRS_VXWORKS_MINOR < 9)))))
        if (localtime_r(&epochTime, &broken) != OK)
            throw Poco::SystemException("cannot get local time");
#else
        if (!localtime_r(&epochTime, &broken))
            throw Poco::SystemException("cannot get local time");
#endif
        _tzd = Timezone::utcOffset() + Timezone::dst(_dateTime.timestamp());
#endif
        adjustForTzd();
    }
    else
    {
        int dst;
        dstOffset(dst);
        _tzd = (Timezone::utcOffset() + dst);
    }
}

It was difficult to reproduce even to me, I never understand why or when that happens...I suppose is related to some thread call condition

github-actions[bot] commented 11 months ago

This issue is stale because it has been open for 365 days with no activity.