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.



  • If signals of your process are still pending, you should destroy the object using

    @
    proc->deleteLater();
    @



  • excellent, this is exactly what I was looking for.

    Thanks!



  • [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.



  • I should probably also mention I need the signals so that I can monitor the output as it progresses, just a dump at the end is not granular enough for my needs.

    -=ben



  • QProcess, by it's nature, runs asynchronously by design. Why do you put that into a separate thread? Connecting to signals should be sufficient.



  • 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



  • That sounds reasonable. But in that case, I would define my own signals and emit them after the process has finished and you have read stdout and/or stderr.



  • If I wanted to implement my own waitForFinished() what would you recommend?



  • 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.


Log in to reply
 

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