Deleting QProcess after finish
-
I am creating a process and then call waitForFinished, then delete the process. Problem is I recieve readyReadStandardError signals after waitForFinished and subsequently after I have deleted the process which causes an error when I try and read the output from the now deleted process.
@
QProcess * proc = new QProcess();
// setup args, connect signals, etc..
proc->start(...);
proc->waitForFinished(-1);delete proc;
<-- sometime after here readyReadStandardError() signals get emitted from the deleted proc.
@My question is, when can I safely delete the process and still get all of its signals?
Thanks.
-
I haven't verified this but I assume that QProcess emits various signals which aren't processed because QProcess::waitForFinished() blocks your event loop and thus no event handling (signal processing) occours. As soon as QProcess::waitForFinished() returns the events pending in the event loop are processed and the pending signals are emitted, even though your QProcess has been already deleted.
QProcess offers you two possible interfaces:
- a synchronous interface using QProcess::waitForFinished(), which means your application is blocked until the executed process is finished
- an asynchronous interface using appropriate signals (eg. QProcess::finished()), which means your application continues execution and is notified about state changes of the executed process via signals
There is no sense in mixing both. You either use the synchronous interface (which might lead to a frozen user interface because your event loop is blocked) or the asynchronous interface with signals and slots.
-
The signal queue is also what I am suspecting to be the cause, I suppose I could emit my own signal once waitForFinished() returns and delete the process there. This is of course assuming the signal queue is the culprit and that I would be gauranteed that my emit would occur after anything already in the queue.
-
[quote author="mirswith" date="1316459702"]The signal queue is also what I am suspecting to be the cause, I suppose I could emit my own signal once waitForFinished() returns and delete the process there. This is of course assuming the signal queue is the culprit and that I would be gauranteed that my emit would occur after anything already in the queue.[/quote]
Why do you even connect to signals of QProcess in the first place?
They have no chance to be delivered, because your thread is suspended until waitForFinished() returns - thus no event processing occours. As soon as waitForFinished() returns it is absolutely safe to process to QProcess output and delete the QProcess (given that no signals have been connected).
You either use signals or you use waitForFinished(). There is no sense in using both.
-
Actually I am running a number of QProcesses in a QThread which separates them from my GUI thread and I am receiving signals off of them. I am using the signals purely to capture standard/error out messages, however I have not tried to just read them after waitForFinished() which might work just fine.
-
Its the architecture of the tool I am developing. It's basically a system that queues a number of jobs, each job get's its own QThread to run in. A job then consists of one or more tasks defined with javascript, these scripts can then execute system tools using QProcess and I want these to be synchronous in their execution order.
-=ben
-
The usual way of defining a new signal. That completely depends on your use case and needs. The outline is basically:
@
class MyProcessWorker : public ...
{
// constructors etc.signals:
myProcessFinished(const QString &message);protected:
void runMyProcess();
};void MyProcessWorker::runMyProcess()
{
QProcess proc;
proc.start( args... );
proc.waitForFinished(-1);QByteArray stdout = proc.readAllStandardOutput(); QByteArray stderr = proc.readAllStandardError(); QString msg = whatever you make out of stdout and stderr; emit myProcessFinished(msg);
}
@ -
Thanks, I understand signals/slots I was asking because I was running into an issue where I wanted a different thread to be able to cancel the process and if I sit on QProcesses waitForFinished() and then call kill() from a different thread then nasty things happen. :)
What I did in the end was simply set a bool that determines if I should kill the process and then after I call the process I do:
@
while(proc->waitForFinished(250))
{
if( _killRequested ) proc->kill();
}
@This seems to be working well.