Solved 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
andQTimer
are local and live in the thread they are created (and should be destroyed in the said thread).Any help?
-
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 aQSemaphore
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 inheritsQThread
, I know this is not the most preferable way to do things but it's the way it is) which ownsQScriptEngine
instance and inrun
it hasvoid 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 threadwait
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) -
@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.
ButstopWaiting()
only controlsQEventLoop
, i.e. it shouldn't affect timer, local towait
.I'm not sure how to do this because in qt creator I can only go to
QTimer
header, notcpp
(and I really don't want to compile my own Qt ;P) -
@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)?
-
@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.