PDA

View Full Version : QScriptEngine queued signal arrives during evaluate or destruction



Statix
25th April 2012, 00:12
I have a large amount of exported C++ QObject service (ServiceA) exported into multiple QtConcurrent threads which each contain a QScriptEngine.
The engines all execute different script code and the lifetime of the script exists until i terminate the QEventLoop which is running in the same thread the QScriptEngine was created.

The problem i'm randomly running into is that the scripts will call connect on an exposed C++ object and set the receiver as a function in the script, however I can sometimes get segmentation faults coming out of the EventLoop (way down in the call in the ScriptEngine for QMetaObject invokeMethod where a Q_ASSERT(slot && slot.isObject()) will fail. _ServiceA is running in another thread yet exposed to the engine, Example script code:


Action.execute = function()
{
....
_ServiceA.notifyCommandComplete.connect(Action.han dleCommandComplete);
...
}
Action.handleCommandComplete = function(commandId)
{
if(commandId == Action.waitingCommandId)
{
_ServiceA.notifyCommandComplete.disconnect(Action. handleCommandComplete); // unregister from the service
...
}
}


C++ Side


//This is executed as a QtConcurrent::run function
QEventLoop eventLoop;
connect( this, SIGNAL(signal_actionComplete()), &eventLoop, SLOT(quit()));
if(Invoke()) //Invoke is a call to engine.call("Action.execute") from same thread.
{
eventLoop.exec();
}
disconnect(this, SIGNAL(signal_actionComplete()), &eventLoop, SLOT(quit()));



_ServiceA can signal notifyCommandComplete at any time and multiple times asynchroniously so I'm thinking that my QScriptEngine may be evaluating when the slot is invoked and causing a cross-thread access problem (How exactly does QScriptEngine prevent script slots from executing while evaluating?)

This code works 99% of the time so it is definetly some race condition going on with the QueuedConnection events. Theoretically the Action.handleComandComplete should always exist so i'm not sure how the assert would fail in that case? I'm wondering if converting all of my signals (alot of them) to BlockingQueuedConnection may fix the problem but it also leaves the case of QScriptEngine signal disconnection kind of open (how can i guarantee the disconnect occured and voided any incoming events)?

pkj
26th April 2012, 06:09
Why haven't you used QScriptEngine::abortEvaluation to abort any evaluations by engine while about to be closed down?

Statix
26th April 2012, 12:50
I could try that but the signal_actionComplete is invoked in the QtScript (the engine aborts its own eventloop), I don't see how it would change the situation unless the actionComplete is getting invoked as DirectConnect in that thread.