QTimer seems to just stop



  • I have an application that uses a QTimer to fire a signal every second to perform some regular display updates. This works great...for about an hour of operation. Then, the timeout handler apparently sees no more timeout() signals. I've added console trace lines at the beginning and end of the handler. Output suggests the final handler execution completes,, but no new ones are announced. Various widgets in the application apparently remain responsive. Nothing in my code explicitly stops the timer.

    Any theories?
    Suggested debugging tactics? It is not feasible to run this within a debugger.

    Using Qt 5.8.0 on Genode, x86_32.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Do you have your device going to sleep ?
    Do you have any other application doing something ?
    What are you doing in the slot connected to that timer ?



  • @acs-sharp said in QTimer seems to just stop:

    Then, the timeout handler apparently sees no more timeout() signals.

    3600ish timeouts and then nothing? It's entirely possible that there is a resource leak, but you need to do a lot investigating first. Memory usage over the life of the program? Putting a QTimer into its own project that does nothing except output a counter value, and then see if it behaves similarly?

    Post the substance of your timeout() slot.



  • @SGaist said in QTimer seems to just stop:

    Do you have your device going to sleep ?

    No--its incapable of this :-)

    Do you have any other application doing something ?

    There are other applications on the system though afaict they are sleeping most of the time.

    What are you doing in the slot connected to that timer ?

    It updates displayed content in various widgets (labels,spinbox, LCDNumber,, ComboBox). I've looked over these for anything that might block (no obvious candidates), and tried commenting them out one by one, but the problem persists. The data (array of integers) it accesses does not entail I/O, but it is memory shared with another thread--the slot handler reads only.



  • @Kent-Dorfman said in QTimer seems to just stop:

    @acs-sharp said in QTimer seems to just stop:

    Then, the timeout handler apparently sees no more timeout() signals.

    3600ish timeouts and then nothing? It's entirely possible that there is a resource leak,

    Interesting. The resource leak angle seems worth pursuing. Would I be naive in thinking that if memory ran out I'd get a warning message, or at least a segfault?

    Are there Qt functions for monitoring resources it manages? (I don't have access to the usual C tools, e.g. valgrind, in this environment.)



  • @acs-sharp
    You talk about multiple threads. If the thread with the timer doesn't hit its event loop your timer doesn't fire. Or if your thread gets blocked, perhaps waiting on the other one. Just saying.

    Thought: Assuming your OS allows a second timer, create a QTimer timer2 alongside your timer. It's sole job is log the https://doc.qt.io/qt-5/qtimer.html#remainingTime-prop of your actual timer. See how that behaves doing its logging, does it continue or seem to stop too? See what it reports for real timer's remainingTime when that finally seems to stop ticking?



  • @JonB said in QTimer seems to just stop:

    @acs-sharp
    You talk about multiple threads. If the thread with the timer doesn't hit its event loop your timer doesn't fire. Or if your thread gets blocked, perhaps waiting on the other one. Just saying.

    That hypothesis has indeed worried me, however I disconnected the two threads but the problem persists.

    Thought: Assuming your OS allows a second timer, create a QTimer timer2 alongside your timer. It's sole job is log the https://doc.qt.io/qt-5/qtimer.html#remainingTime-prop of your actual timer. See how that behaves doing its logging, does it continue or seem to stop too? See what it reports for real timer's remainingTime when that finally seems to stop ticking?

    That was an interesting experiment--thanks for the suggestion. Both timers stop on the same second (~4280). Timer 2 last states that timer1 has 994 remaining; we never hear from either timer after that. I would suppose, "oh, something is blocking the event loop", but the buttons on the window continue to work after the timers stop, which would seem inconsistent with a blocked event loop, no? Could the QTimer instance's memory be getting clobbered thereby stopping the timer(s)? I will try rearranging their position in RAM....



  • @acs-sharp
    That's about what I kind of expected. It's telling us something, but I'm not sure what! Next steps:

    • I'm not quite sure if you can do this, but can you now move timer2 into its own thread and see how it behaves? It probably doesn't need to log timer1's remaining time, because you know what happens to that, it can probably just log itself. You want to know whether that keeps ticking after timer1 stops?

    • It might be time to try @Kent-Dorfman's suggestion: just a standalone project/executable which does nothing but logs a timer, if that too stops then...?

    • Let's be clear: you say you have two threads. Does your timer1 run in the same thread as your GUI (which you say remains responsive), or does it run in the other thread??



  • @JonB said in QTimer seems to just stop:

    • I'm not quite sure if you can do this, but can you now move timer2 into its own thread and see how it behaves? It probably doesn't need to log timer1's remaining time, because you know what happens to that, it can probably just log itself. You want to know whether that keeps ticking after timer1 stops?

    I think I managed this:

    class TimerThread : public QThread
    {
        Q_OBJECT
        void run() override
        {
            QTimer  qtimer2 {this};
            qDebug("TimerThread starting...");
            QObject::connect( &qtimer2, SIGNAL(timeout()), this,
                             SLOT(timer2Update()) );
            qtimer2.start(1000);  // start timer2
            //
            exec();               // start even loop
            qDebug("TimerThread exits!");
        }
    private slots:
        void timer2Update();
    };
    

    An instance of TimerThread is created and started in the constructor for the main window. (Hope that is what you proposed. The timeout handler prints a message on the console every second. It stops at the same time as the timer in the main UI thread.

    • It might be time to try @Kent-Dorfman's suggestion: just a standalone project/executable which does nothing but logs a timer, if that too stops then...?

    Agreed. It will be a bit of work, but feasible. However if anybody has a brilliant hypothesis that would short-circuit that, I'd be really pleased ;-)

    • Let's be clear: you say you have two threads. Does your timer1 run in the same thread as your GUI (which you say remains responsive), or does it run in the other thread??

    Yes, timer1 runs in the same thread as the GUI, which does remain responsive. It is created in the MainWindow ctor.



  • @acs-sharp

    It stops at the same time as the timer in the main UI thread.

    Now, if only we knew what that was telling us...! :)

    It does not necessarily matter about creating a separate application with a timer. It is time(!) now for you to simply change your current timer to only log to file, not "perform some regular display updates" (nor access that shared array). Does that too stop, or was it only because of the display updates it has been performing?



  • @JonB said in QTimer seems to just stop:

    @acs-sharp

    It stops at the same time as the timer in the main UI thread.

    It does not necessarily matter about creating a separate application with a timer. It is time(!) now for you to simply change your current timer to only log to file, not "perform some regular display updates" (nor access that shared array). Does that too stop, or was it only because of the display updates it has been performing?

    Done. The original timer now only increments a static variable counter and prints its value to stderr (every 5th count). It does not touch any shared memory or perform any display updates or anything else. But, timeout events still stop--and, at about the same number of ticks: (4280+/-5, 1hr 11min).

    Well, what if I run the clock faster: update at 200ms instead of 1sec? It still stops at about the same wall clock time (1hr 10min), even thought the number of timeout events processed is 5x higher. My conclusion is that it is not the timeout event processing that is killing the clock(s). But something is killing them, and it appears to be tied to wall-clock time.

    I am tempted to add a button that will try to restart the timer when pressed.


  • Qt Champions 2018

    Please show us the complete code - where does TimerThread live? I would guess in the main thread which means timer2Update() is also executed in the main thread.



  • Hi, could the stop be due to a 2^32 wraparound? Because 4294967296 (2^32) microseconds is 4295 seconds.



  • @hskoglund

    Hi, could the stop be due to a 2^32 wraparound? Because 4294967296 (2^32) microseconds is 4295 seconds.

    It might have been nice if you'd quoted it in minutes, I had to go use calc! 71 minutes, and OP says it works for about an hour, then specifically 1:10, very good spot! But where do you think this happening? I can't see that QTimer stops working, the docs would say so....

    @acs-sharp
    Is there anything in your code which could be sensitive to this? You are 32-bit....
    You said at the beginning:

    Using Qt 5.8.0 on Genode, x86_32.

    I know nothing, what is "Genode"? If it's some embedded system(??), does it have its own clock being leveraged by Qt which might wrap??



  • @JonB Google thinks it's from Germany https://www.genode-labs.com

    About 32-bit overflows, actually the Qt docs mentions it can happen for QElapsedTimer



  • @acs-sharp
    Right! In view of the above: At present you QTimer::start() and leave it to tick forever. Now, for a test, at some point before 71 minutes make your code stop that timer and completely restart it, or delete it and create a new one, or whatever. Do you no longer stop getting timeouts after 71 minutes? It's a workaround, if not a resolution :)



  • @JonB said in QTimer seems to just stop:

    I know nothing, what is "Genode"? If it's some embedded system(??), does it have its own clock being leveraged by Qt which might wrap??

    I'm pretty sure this is what the OP was refering to...
    https://en.wikipedia.org/wiki/Geode_(processor)



  • @hskoglund said in QTimer seems to just stop:

    @JonB Google thinks it's from Germany https://www.genode-labs.com

    About 32-bit overflows, actually the Qt docs mentions it can happen for QElapsedTimer

    Aha! That's a really intriguing theory--with an obvious workaround to try.
    I will pursue this, and report back here, hopefully with data useful to others.

    Also, you have the right Genode: https://genode.org/
    There is no actual OS as such underneath the application I'm debugging, just a seL4 microkernel and some peer components.



  • @JonB said in QTimer seems to just stop:

    @acs-sharp
    Right! In view of the above: At present you QTimer::start() and leave it to tick forever. Now, for a test, at some point before 71 minutes make your code stop that timer and completely restart it, or delete it and create a new one, or whatever. Do you no longer stop getting timeouts after 71 minutes? It's a workaround, if not a resolution :)

    Good workaround discovered. Thanks to all who responded for your help on this!

    Starting and stopping the QTimer did not help, nor did operating it in one-shot mode. However replacing it with a native periodic timer did prove to be a good workaround--it just emits a signal that is handled by the window. Experimentally, the gist of the QTimer-based code seems to work correctly in Linux, so I'm guessing the conjecture that the underlying clock source port has a limitation, e.g. counter word size, is most likely correct. I will take this up with the vendor anon.


Log in to reply