Timers cannot be stopped from another thread.



  • I get

    QObject::killTimer: Timers cannot be stopped from another thread
    QObject::~QObject: Timers cannot be stopped from another thread
    

    And my application either hangs indefinitely or crashes with SISEGV.
    But I don't understand what may cause this/how to workaround this, since the offending code is rather simple:

    void <className>:wait(const int &milliseconds)
    {
    	QEventLoop loop;
    	QObject::connect(this, SIGNAL(stopWaiting()), &loop, SLOT(quit()), Qt::DirectConnection);
    	QTimer t;
    	connect(&t, SIGNAL(timeout()), &loop, SLOT(quit()), Qt::DirectConnection);
    	t.start(milliseconds);
    	loop.exec();
    }
    

    Which is called from QScriptEngine evaluate which may run in a dedicated thread (basically there is script runner thread which has QScriptEngine and evaluates some js script which may call this function wait, the problem is - sometimes when I call abortEvaluation it gets stuck in wait or just crashes with the output above.
    And I don't see how this can be possible since both, QEventLoop and QTimer are local and live in the thread they are created (and should be destroyed in the said thread).

    Any help?


  • Qt Champions 2016

    It's not quite clear what is run in which thread context. Can you elaborate on that. In any case this isn't the way to put a thread barrier, you either should use a QWaitCondition or a QSemaphore for that.



  • @kshegunov said in Timers cannot be stopped from another thread.:

    QWaitCondition

    I think you've confused what wait is doing here. It's not controlling any threading, it just control script execution - it simulates waiting.
    So I have a thread class (which inherits QThread, I know this is not the most preferable way to do things but it's the way it is) which owns QScriptEngine instance and in run it has

    void ScriptThread::run()
    {
    	mEngine->evaluate(mScript);
    
            ...
    

    the object with wait method is registered in the script engine and is called from inside the script.

    And I'm not sure how the thread context would impact the QTimer here, since it's local to the call (created on stack) and if I understand correctly - it should be both created and destroyed in whichever thread wait was called, am I wrong? Also, is where a way to debug these errors? For example to find out which timer exactly outputs this message? (and place a breakpoint there ideally)


  • Qt Champions 2016

    @flashmozzg said in Timers cannot be stopped from another thread.:

    I think you've confused what wait is doing here.

    It's quite possible, that's why I wanted a bit more info.

    which owns QScriptEngine

    How? Can you show the relevant code?

    it's local to the call (created on stack) and if I understand correctly - it should be both created and destroyed in whichever thread wait was called, am I wrong?

    No you're correct, at least in the ordinary case. Here however it isn't exactly clear what thread calls wait. I'd start by making all the connections Qt::AutoConnection type. Secondly I'd attach one additional slot for each signal and make sure that <className>::stopWaiting() is called from the same thread as <className>::wait() (which I suspect might be the problem.)

    Also, is where a way to debug these errors?

    Best way I've found is to compile your debug Qt version and just put a breakpoint in Qt's source (where the warning is raised). Then you can inspect the call stack and see what sequence of calls led to this.

    Kind regards.



  • @kshegunov said in Timers cannot be stopped from another thread.:

    How? Can you show the relevant code?

    It's created like so:

    QSciptEngine *engine;
    ...
    ScriptThread * const thread = new ScriptThread(..., engine, ...);
    ...
    engine->moveToThread(thread);
    

    @kshegunov said in Timers cannot be stopped from another thread.:

    No you're correct, at least in the ordinary case. Here however it isn't exactly clear what thread calls wait. I'd start by making all the connections Qt::AutoConnection type. Secondly I'd attach one additional slot for each signal and make sure that <className>::stopWaiting() is called from the same thread as <className>::wait() (which I suspect might be the problem.)

    I'll try and see what I can do (this part of code is sort of an external lib, so I'd rather avoid changing it's code, if possible, but if it's legit bug I can't see why not (though maybe it's because I use it incorrectly).

    @kshegunov said in Timers cannot be stopped from another thread.:

    Best way I've found is to compile your debug Qt version and just put a breakpoint in Qt's source (where the warning is raised). Then you can inspect the call stack and see what sequence of calls led to this.
    But stopWaiting() only controls QEventLoop, i.e. it shouldn't affect timer, local to wait.

    I'm not sure how to do this because in qt creator I can only go to QTimer header, not cpp (and I really don't want to compile my own Qt ;P)


  • Qt Champions 2016

    @flashmozzg said in Timers cannot be stopped from another thread.:

    It's created like so

    Looks okay to me.

    I'm not sure how to do this because in qt creator I can only go to QTimer header, not cpp (and I really don't want to compile my own Qt ;P)

    You won't be able to do it without the debug information (and corresponding sources).



  • @kshegunov said in Timers cannot be stopped from another thread.:

    You won't be able to do it without the debug information (and corresponding sources).

    Is there an easy way to get this on Windows (i.e. using Maintenance tool, though I don't see something like that anywhere)?


  • Moderators

    @flashmozzg You can easily install Qt sources using Qt Maintenance Tool. If you need a debug Qt build you will need to build Qt by yourself.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.