From 10:00 CET Friday 22nd November we will adjust how the server works to deal with some recently reported problems. Therefore there may be a load problem, if you experience more problems than usual trying to access the forum then please PM AndyS or any of the moderators so they can inform me.


The constructors QQmlApplicationEngine and QSettings spoil the time zone (daylight)



  • I came across the strange behavior of the QQmlApplicationEngine constructor. The minimum code is main.cpp:

    #include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QDebug>
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        qDebug() << "1ST timezone=" << timezone << " daylight=" << daylight;
        tzset();
        qDebug() << "2ND timezone=" << timezone << " daylight=" << daylight;
    
        QQmlApplicationEngine engine;
    
        qDebug() << "3ND timezone=" << timezone << " daylight=" << daylight;
    
        return app.exec();
    }
    

    Result of work:

    1ST timezone= 0  daylight= 0
    2ND timezone= -10800  daylight= 1
    3ND timezone= -10800  daylight= 0
    

    That is, after the QQmlApplicationEngine constructor is triggered, daylight spoils (switch to zero).

    I was surprised, but it's necessary to work and therefore I tried to get around this case like this:

    long saveTimezone=timezone;
    int saveDaylight=daylight;
    
    QQmlApplicationEngine engine;
    
    timezone=saveTimezone;
    daylight=saveDaylight;
    

    It worked, but in the project I still found another one place in which the same behavior, after the QSettings constructor (but already in the heap). Looks like that:

    qDebug() << "CURRENT timezone=" << timezone << " daylight=" << daylight;
    QSettings *config=new QSettings(fileName, QSettings::IniFormat, this);
    qDebug() << "CURRENT timezone=" << timezone << " daylight=" << daylight;
    
    CURRENT timezone= -10800  daylight= 1
    CURRENT timezone= -10800  daylight= 0
    

    But in a minimal code, I could not repeat this.

    Where else the variable daylight can spoil, I do not know, but I do not rule out such probabilities. The problem is that my project uses a legacy library that works with daylight, and because of these problems it gives the wrong time.

    Questions: what kind of problem is this, why do some Qt classes spoil daylight, how is this thing guaranteed to work around?

    PS: The project file that would quickly compile a minimal example (only the project file and main.cpp will be required):

    time.pro

    CONFIG+=c++11
    CONFIG+=qml_debug
    QT+=gui
    QT+=core
    QT+=quick
    QT+=widgets
    SOURCES += main.cpp
    DEFINES += QT_DEPRECATED_WARNINGS
    

  • Lifetime Qt Champion

    Hi,

    Intriguing !

    What version of Qt are you using ?
    On what platform ?



  • @SGaist
    Debian Linux Stable 64 bit, Qt 5.10.1 by official site.


  • Qt Champions 2017

    @xintrea said in The constructors QQmlApplicationEngine and QSettings spoil the time zone (daylight):

    Qt 5.10.1 by official site

    You mean downloaded from qt.io, correct? Because debian doesn't provide that in stable, but the current Qt version for the testing flavor is exactly 5.10.1.



  • @kshegunov
    Yes. I use Debian Stable 9 (64-bit) with all updates:

    > lsb_release -a
    No LSB modules are available.
    Distributor ID: Debian
    Description:    Debian GNU/Linux 9.3 (stretch)
    Release:        9.3
    Codename:       stretch
    

    I get Qt from qt.io as file qt-opensource-linux-x64-5.10.1.run.


  • Lifetime Qt Champion

    Do you get the same behaviour if you use Debian's provided version of Qt ?



  • @SGaist

    I not experiment with Qt version.

    But i debug this situation. I set watchpoint to system global variable daylight. This is stack if run constructor QQmlApplicationEngine:

    (gdb) where
    #0  update_vars () at tzset.c:156
    #1  0x00007ffff3c8a569 in __tzset_parse_tz (tz=<optimized out>) at tzset.c:391
    #2  0x00007ffff3c8c27b in __tzfile_compute (timer=<optimized out>, use_localtime=use_localtime@entry=1, 
        leap_correct=leap_correct@entry=0x7fffffffd938, leap_hit=leap_hit@entry=0x7fffffffd934, tp=tp@entry=0x7fffffffd980)
        at tzfile.c:691
    #3  0x00007ffff3c8ac44 in __tz_convert (timer=0x7fffffffd978, use_localtime=1, tp=0x7fffffffd980) at tzset.c:624
    #4  0x00007ffff608230a in ?? () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Qml.so.5
    #5  0x00007ffff608afab in ?? () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Qml.so.5
    #6  0x00007ffff60692db in QV4::ExecutionEngine::ExecutionEngine(QV4::EvalISelFactory*) ()
       from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Qml.so.5
    #7  0x00007ffff61c949a in QV8Engine::QV8Engine(QJSEngine*) () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Qml.so.5
    #8  0x00007ffff5fffb14 in QJSEngine::QJSEngine(QJSEnginePrivate&, QObject*) ()
       from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Qml.so.5
    #9  0x00007ffff6127969 in QQmlEngine::QQmlEngine(QQmlEnginePrivate&, QObject*) ()
       from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Qml.so.5
    #10 0x00007ffff61b44e0 in QQmlApplicationEngine::QQmlApplicationEngine(QObject*) ()
       from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Qml.so.5
    

    And this is stack if run constructor QSettings:

    (gdb) where
    #0  update_vars () at tzset.c:156
    #1  0x00007ffff3c8a569 in __tzset_parse_tz (tz=<optimized out>) at tzset.c:391
    #2  0x00007ffff3c8c27b in __tzfile_compute (timer=<optimized out>, use_localtime=use_localtime@entry=1, 
        leap_correct=leap_correct@entry=0x7fffffffd3f8, leap_hit=leap_hit@entry=0x7fffffffd3f4, tp=tp@entry=0x7fffffffd4a0)
        at tzfile.c:691
    #3  0x00007ffff3c8ac44 in __tz_convert (timer=0x7fffffffd498, use_localtime=1, tp=0x7fffffffd4a0) at tzset.c:624
    #4  0x00007ffff4dc8709 in QDateTime::setMSecsSinceEpoch(long long) () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5
    #5  0x00007ffff4dcab4d in QDateTime::fromMSecsSinceEpoch(long long, Qt::TimeSpec, int) ()
       from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5
    #6  0x00007ffff4dcb00d in QDateTime::fromMSecsSinceEpoch(long long) () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5
    #7  0x00007ffff4e87226 in QFileInfo::fileTime(QFileDevice::FileTime) const ()
       from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5
    #8  0x00007ffff4e8732e in QFileInfo::lastModified() const () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5
    #9  0x00007ffff4ec90e1 in ?? () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5
    #10 0x00007ffff4ec98cd in ?? () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5
    #11 0x00007ffff4eca4b4 in ?? () from /opt/qt_5_10_1/5.10.1/gcc_64/lib/libQt5Core.so.5
    #12 0x00007ffff4eca57f in QSettings::QSettings(QString const&, QSettings::Format, QObject*)
    

    Really, QQmlApplicationEngine and QSettings is change timezone and, therefore, daylight.



  • @SGaist

    And function update_vars() is:

    151 static void                                                                                                              
    152 internal_function                                                                                                        
    153 update_vars (void)                                                                                                       
    154 {                                                                                                                        
    155   __daylight = tz_rules[0].offset != tz_rules[1].offset;                                                                 
    156   __timezone = -tz_rules[0].offset;                                                                                      
    157   __tzname[0] = (char *) tz_rules[0].name;                                                                               
    158   __tzname[1] = (char *) tz_rules[1].name;                                                                               
    159                                                                                                                          
    160   /* Keep __tzname_cur_max up to date.  */                                                                               
    161   size_t len0 = strlen (__tzname[0]);                                                                                    
    162   size_t len1 = strlen (__tzname[1]);                                                                                    
    163   if (len0 > __tzname_cur_max)                                                                                           
    164     __tzname_cur_max = len0;                                                                                             
    165   if (len1 > __tzname_cur_max)                                                                                           
    166     __tzname_cur_max = len1;                                                                                             
    167 }
    

Log in to reply