[Interest] Finished signal from QProcess!

1,396 views
Skip to first unread message

Lata Agrawal

unread,
Feb 28, 2012, 11:39:52 PM2/28/12
to inte...@qt-project.org
Hi,

I am running console application C1 in QProcess. I am starting this console application C1 from another console application C2. Problem is:
I am only getting finished signal from C1 when I use waitforfinshed() else I am not getting finished signal from C1. Here is the code:

                QString strProgram;
                strProgram = <Path to C1>;
                updateProc->setProcessChannelMode(QProcess::ForwardedChannels);
                connect(updateProc, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(procStarted(int,QProcess::ExitStatus)), Qt::DirectConnection);
                updateProc->setStandardOutputProcess(this->thread()->parent());
                updateProc->start(strProgram, arguments);

                //Download is over, indicate through bool variable that next downlaod can be started
                if(updateProc->waitForFinished(-1))
                {
                    qDebug("Update process finished!\n");
                }
                else
                {
                    qDebug("Update process not yet finished!\n");
                }

void FloDownloadManager::procStarted(int retVal ,QProcess::ExitStatus exitStat)
{
    qDebug("Update process finished automatically!\n");
    if(currentExecutingPriority == AdsUpdate)
    {
        emit adUpdateDone();
    }
    blnStartNextUpdate = true;

    updateProc->deleteLater();
}

If I comment the waitforfinished() code, I don't get the finished signal. But if I include the waitforfinished() signal, I don't get the finished signal. Code for C1 is as follows:

#include <QtCore/QCoreApplication>
#include "updater.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug("Inside Updater\n");

    QTimer::singleShot(5000, &a, SLOT(quit()));
    qDebug("returning from Updater process!@@@@@@@@\n");

    return 0;
}

I read on other forums that if main process does not wait for child process to finish like using waitforfinished, then finished signal will not be sent to main process, rather child process after finishing will become defunct or zombie. In my code above, if I use waitforfinished, then main process does receive finished signal. 

Is there any way by which main process can receive finished signal without waiting for child process to finish?

Regards,
Lata


--
                                

Lata Agrawal
Senior Developer
9699750643
En Route Media Pvt. Ltd.
                                

Mandeep Sandhu

unread,
Feb 29, 2012, 12:06:52 AM2/29/12
to Lata Agrawal, inte...@qt-project.org
On Wed, Feb 29, 2012 at 10:09 AM, Lata Agrawal
<lata.a...@enrouteinc.com> wrote:
> Hi,
>
> I am running console application C1 in QProcess. I am starting this console
> application C1 from another console application C2. Problem is:
> I am only getting finished signal from C1 when I use waitforfinshed() else I
> am not getting finished signal from C1. Here is the code:

Does your console app C1 quit after completing its work? Or is the
event loop still running in C1?...have your called
QApplication::quit/exit in C1 after it's done with it work? If not
then C1 will continue to run untill explicitly exited (or killed from
outside).

>
>                 QString strProgram;
>                 strProgram = <Path to C1>;
>
> updateProc->setProcessChannelMode(QProcess::ForwardedChannels);
>                 connect(updateProc,
> SIGNAL(finished(int,QProcess::ExitStatus)),
> SLOT(procStarted(int,QProcess::ExitStatus)), Qt::DirectConnection);

'procStarted' seems to be strange name for a slot handling the
'finished' singla!! :)


>
> updateProc->setStandardOutputProcess(this->thread()->parent());
>                 updateProc->start(strProgram, arguments);

Why is this needed? Is C2 processing o/p of C1...or do you simply want
to print stdout of C1 in C2's stdout (if so, then you've already done
that by setting the channel mode above)?

>
>                 //Download is over, indicate through bool variable that next
> downlaod can be started
>                 if(updateProc->waitForFinished(-1))
>                 {
>                     qDebug("Update process finished!\n");
>                 }
>                 else
>                 {
>                     qDebug("Update process not yet finished!\n");
>                 }
>
> void FloDownloadManager::procStarted(int retVal ,QProcess::ExitStatus
> exitStat)
> {
>     qDebug("Update process finished automatically!\n");
>     if(currentExecutingPriority == AdsUpdate)
>     {
>         emit adUpdateDone();
>     }
>     blnStartNextUpdate = true;
>
>     updateProc->deleteLater();
> }
>
>
> If I comment the waitforfinished() code, I don't get the finished signal.
> But if I include the waitforfinished() signal, I don't get the finished
> signal. Code for C1 is as follows:
>
> #include <QtCore/QCoreApplication>
> #include "updater.h"
>
> int main(int argc, char *argv[])
> {
>     QCoreApplication a(argc, argv);
>
>     qDebug("Inside Updater\n");
>
>     QTimer::singleShot(5000, &a, SLOT(quit()));
>     qDebug("returning from Updater process!@@@@@@@@\n");
>
>     return 0;
> }

You have not started the apps event loop!!!...what do you expect it
do? This program will exit out immediately! You need to do a.exec()
for the timer signal to be processed.

>
> I read on other forums that if main process does not wait for child process
> to finish like using waitforfinished, then finished signal will not be sent
> to main process, rather child process after finishing will become defunct or
> zombie. In my code above, if I use waitforfinished, then main process does
> receive finished signal.

AFAIK, in linux, if the parent process dies before a child process
finishes, it is re-parented to init (process with pid 1). This is
called an 'orphaned' process. Not to be confused with a zombie/defunct
in which a process has exited, but it's entry has not been removed
from process table.

More:
http://en.wikipedia.org/wiki/Orphan_process
http://en.wikipedia.org/wiki/Zombie_process

>
> Is there any way by which main process can receive finished signal without
> waiting for child process to finish?

Yes, by connecting to the child QProcess's 'finished' signal. Thats
what the signal is there for! :) It tells the parent when a process
has exited and with what exit code.

HTH,
-mandeep

> Regards,
> Lata
>
>
> --
>
>
> Lata Agrawal
> Senior Developer
> 9699750643
> En Route Media Pvt. Ltd.
>
>
>

> _______________________________________________
> Interest mailing list
> Inte...@qt-project.org
> http://lists.qt-project.org/mailman/listinfo/interest
>
_______________________________________________
Interest mailing list
Inte...@qt-project.org
http://lists.qt-project.org/mailman/listinfo/interest

Lata Agrawal

unread,
Feb 29, 2012, 1:46:51 AM2/29/12
to Mandeep Sandhu, inte...@qt-project.org
On 29 February 2012 10:36, Mandeep Sandhu <mandeeps...@gmail.com> wrote:
On Wed, Feb 29, 2012 at 10:09 AM, Lata Agrawal
<lata.a...@enrouteinc.com> wrote:
> Hi,
>
> I am running console application C1 in QProcess. I am starting this console
> application C1 from another console application C2. Problem is:
> I am only getting finished signal from C1 when I use waitforfinshed() else I
> am not getting finished signal from C1. Here is the code:

Does your console app C1 quit after completing its work? Or is the
event loop still running in C1?...have your called
QApplication::quit/exit in C1 after it's done with it work? If not
then C1 will continue to run untill explicitly exited (or killed from
outside).

yes, on using ps command in terminal,  I can see the process C1 but in defunct state. I used return a.exec() in C1 along with a timer QTimer::singleshot(0, &a, SLOT(quit()).

>
>                 QString strProgram;
>                 strProgram = <Path to C1>;
>
> updateProc->setProcessChannelMode(QProcess::ForwardedChannels);
>                 connect(updateProc,
> SIGNAL(finished(int,QProcess::ExitStatus)),
> SLOT(procStarted(int,QProcess::ExitStatus)), Qt::DirectConnection);

'procStarted' seems to be strange name for a slot handling the
'finished' singla!! :)
I know. actually i created this slot for started() signal, but then eventually connected it for finished signal.
>
> updateProc->setStandardOutputProcess(this->thread()->parent());
>                 updateProc->start(strProgram, arguments);

Why is this needed? Is C2 processing o/p of C1...or do you simply want
to print stdout of C1 in C2's stdout (if so, then you've already done
that by setting the channel mode above)?
Sorry, this is supposed to be commented.

This I tried but still no finished signal.

>
> I read on other forums that if main process does not wait for child process
> to finish like using waitforfinished, then finished signal will not be sent
> to main process, rather child process after finishing will become defunct or
> zombie. In my code above, if I use waitforfinished, then main process does
> receive finished signal.

AFAIK, in linux, if the parent process dies before a child process
finishes, it is re-parented to init (process with pid 1). This is
called an 'orphaned' process. Not to be confused with a zombie/defunct
in which a process has exited, but it's entry has not been removed
from process table.
You are right. But when I use ps, I se my C1 listed as C1 defunct. If I am not wrong, this means a zombied process, which has finished but whose parent process is still alive. Right?

More:
http://en.wikipedia.org/wiki/Orphan_process
http://en.wikipedia.org/wiki/Zombie_process

>
> Is there any way by which main process can receive finished signal without
> waiting for child process to finish?

Yes, by connecting to the child QProcess's 'finished' signal. Thats
what the signal is there for! :) It tells the parent when a process
has exited and with what exit code.

One more thing, in C2 (the main process, I have called a class which starts an infinite loop and a.exec is called after that which essentially means a.exec() is never called. Is this the reason why I am not getting finished signal? Code is shown below:


int main(int argc, char *argv[])
{
    Class1 downloadMngr;
    downloadMngr.startDownload(); //This starts an infinite loop which waits for items to be added to queue

    return a.exec();  //So this is probably never called.
}

How can I start eventloop in main() while having the functionality in Class1.

Regards,
Lata

HTH,
-mandeep

> Regards,
> Lata
>
>
> --
>
>
> Lata Agrawal
> Senior Developer
> 9699750643
> En Route Media Pvt. Ltd.
>
>
>
> _______________________________________________
> Interest mailing list
> Inte...@qt-project.org
> http://lists.qt-project.org/mailman/listinfo/interest
>

Mandeep Sandhu

unread,
Feb 29, 2012, 3:41:21 AM2/29/12
to Lata Agrawal, inte...@qt-project.org
>
> One more thing, in C2 (the main process, I have called a class which starts
> an infinite loop and a.exec is called after that which essentially means
> a.exec() is never called. Is this the reason why I am not getting finished
> signal? Code is shown below:

Yes it is!!! The event loop needs to be running for it process events
and since you're never executing a.exec() it never gets started.

I'm not sure why the C1 process is being listed as defunct. Can you
provide us with a compilable example which shows the problem?

>
>
> int main(int argc, char *argv[])
> {
>     Class1 downloadMngr;
>     downloadMngr.startDownload(); //This starts an infinite loop which waits
> for items to be added to queue
>
>     return a.exec();  //So this is probably never called.

Correct.

> }
>
> How can I start eventloop in main() while having the functionality in
> Class1.

What is this functionality of C1? It's not clear from your mail. Looks
like you're writing some sort of an application updater (which
downloads a new app and writes it?)?

Can you explain a little more of what you're attempting. Do you need 2
processes in the first place? Can't it be done with a single process
i.e your main app itself?

Regards,
-mandeep

Lata Agrawal

unread,
Feb 29, 2012, 5:30:34 AM2/29/12
to Mandeep Sandhu, inte...@qt-project.org
On 29 February 2012 14:11, Mandeep Sandhu <mandeeps...@gmail.com> wrote:
>
> One more thing, in C2 (the main process, I have called a class which starts
> an infinite loop and a.exec is called after that which essentially means
> a.exec() is never called. Is this the reason why I am not getting finished
> signal? Code is shown below:

Yes it is!!! The event loop needs to be running for it process events
and since you're never executing a.exec() it never gets started.
 
I'm not sure why the C1 process is being listed as defunct. Can you
provide us with a compilable example which shows the problem?

This would happen, if lets say we start a child process using QProcess  from main application and don't start the event loop of main application.  Now when child process stops, since main apps event loop is not running, it doesn't receive the finished hence no one deletes the child process object on heap. Now if you run ps in terminal, you will see child process as defunct.
>
>
> int main(int argc, char *argv[])
> {
>     Class1 downloadMngr;
>     downloadMngr.startDownload(); //This starts an infinite loop which waits
> for items to be added to queue
>
>     return a.exec();  //So this is probably never called.

Correct.

Now when I know the problem, I think I am nearing solving this. Thanks for your help.
 
> }
>
> How can I start eventloop in main() while having the functionality in
> Class1.

What is this functionality of C1? It's not clear from your mail. Looks
like you're writing some sort of an application updater (which
downloads a new app and writes it?)?

Can you explain a little more of what you're attempting. Do you need 2
processes in the first place? Can't it be done with a single process
i.e your main app itself?
I  am trying to create a pre-emptive queue in which each item is a download of different priority. In code above Class1 is a downloadmanager which runs a forever loop and using mutex and waitcondition I wait for new upload being added to queue. Now if a higher priority download is added, current ongoing update has to be stopped. I used QProcess instead of a thread, to start the download because killing a QProcess is neater. Now problem is when an ongoing download ends i.e. its process ends, downlaodmanager should receive a finished signal so that it can process another download in queue.

Hope I have made myself clear. If something is not clear, I can explain again. How do you think I can run forever loop and also start event loop in main process? Or if you can think of a better way of doing this.

Regards,
Lata

Mandeep Sandhu

unread,
Feb 29, 2012, 8:38:34 AM2/29/12
to Lata Agrawal, inte...@qt-project.org
> This would happen, if lets say we start a child process using QProcess  from
> main application and don't start the event loop of main application.  Now
> when child process stops, since main apps event loop is not running, it
> doesn't receive the finished hence no one deletes the child process object
> on heap. Now if you run ps in terminal, you will see child process as
> defunct.

When you say "no one deletes the child process object on heap", I
assume you mean the QProcess instance on the heap. If the child
process exits, why will the OS show it as defunct? The parent process
is still running (due to the infinite loop) and it's child exited
(normally or abnormally does not matter), I don't think thats what is
happening.

>>
>> I  am trying to create a pre-emptive queue in which each item is a
>> download of different priority. In code above Class1 is a downloadmanager
>> which runs a forever loop and using mutex and waitcondition I wait for new
>> upload being added to queue. Now if a higher priority download is added,
>> current ongoing update has to be stopped. I used QProcess instead of a
>> thread, to start the download because killing a QProcess is neater. Now
>> problem is when an ongoing download ends i.e. its process ends,
>> downlaodmanager should receive a finished signal so that it can process
>> another download in queue.

Is this 'download' over a network? If so why do you need a separate
thread/process for it? Have you looked at Qt's networking classes
(QNetworkAccessManager, QTcpSocket etc)?? They provide async API's to
do network IO. You can still manage your 'premptive queue' based
download with it. When a higher priority download is queued, you can
always 'abort' the ongoing download and start the new one and whne
this one finishes, you can restart the abort one (or whatever your app
logic demands). Will that work for you?

-mandeep

Thiago Macieira

unread,
Feb 29, 2012, 9:57:10 AM2/29/12
to inte...@qt-project.org
On quarta-feira, 29 de fevereiro de 2012 14.11.21, Mandeep Sandhu wrote:
> I'm not sure why the C1 process is being listed as defunct. Can you
> provide us with a compilable example which shows the problem?

Because waitpid() is executed in the mainloop. If there's no mainloop,
waitpid() doesn't get executed and the child isn't reaped. It stays as a
zombie.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358

signature.asc

Lata Agrawal

unread,
Feb 29, 2012, 12:24:09 PM2/29/12
to inte...@qt-project.org
Thanks Thiago, for the clarification.

_______________________________________________
Interest mailing list
Inte...@qt-project.org
http://lists.qt-project.org/mailman/listinfo/interest

Lata Agrawal

unread,
Mar 1, 2012, 12:02:46 AM3/1/12
to Mandeep Sandhu, inte...@qt-project.org

Yes, download is over a network. I used thread/process because download process is very time consuming and I have to continuously check for other kinds of downloads. Yes, I can download using  QNetworkAccessManager but then all download will have to be done in either a thread or a process because it is time consuming.

How can I use processEvents in my class process app events?

Regards,
Lata

-mandeep

Mandeep Sandhu

unread,
Mar 1, 2012, 7:22:08 AM3/1/12
to Lata Agrawal, inte...@qt-project.org
> Yes, download is over a network. I used thread/process because download
> process is very time consuming and I have to continuously check for other
> kinds of downloads. Yes, I can download using  QNetworkAccessManager but
> then all download will have to be done in either a thread or a process
> because it is time consuming.

How does that matter? Even if the download takes long, becaue the QNAM
API's are async, you will get a notification when a download
completes. You can then use the req url, stored in the QNetworkReply
object you got when you dispatched the request, to figure out which
request got completed. I still don't see a case for a separate
thread/process for just the download part (maybe I'm missing some
info).

>
> How can I use processEvents in my class process app events?

Umm not sure what you meant here. Why do you manually need to call
processEvents? Are you blocking your event loop somewhere or are you
worried that the time-consuming download will block your event loop?
(the download won't block your event loop).

HTH,
-mandeep


>
> Regards,
> Lata
>>
>>
>> -mandeep
>
>
>
>
> --
>
>
> Lata Agrawal
> Senior Developer
> 9699750643
> En Route Media Pvt. Ltd.
>
>

Mandeep Sandhu

unread,
Mar 1, 2012, 8:48:44 AM3/1/12
to Thiago Macieira, inte...@qt-project.org
> On quarta-feira, 29 de fevereiro de 2012 14.11.21, Mandeep Sandhu wrote:
>> I'm not sure why the C1 process is being listed as defunct. Can you
>> provide us with a compilable example which shows the problem?
>
> Because waitpid() is executed in the mainloop. If there's no mainloop,
> waitpid() doesn't get executed and the child isn't reaped. It stays as a
> zombie.

Ok, yes that explains it. Though I guess when the parent exits, init
reaps this zombie?

Thanks,
-mandeep

>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>   Software Architect - Intel Open Source Technology Center
>      PGP/GPG: 0x6EF45358; fingerprint:
>      E067 918B B660 DBD1 105C  966C 33F5 F005 6EF4 5358
>

Lata Agrawal

unread,
Mar 6, 2012, 5:47:36 AM3/6/12
to Mandeep Sandhu, inte...@qt-project.org
On 1 March 2012 17:52, Mandeep Sandhu <mandeeps...@gmail.com> wrote:
> Yes, download is over a network. I used thread/process because download
> process is very time consuming and I have to continuously check for other
> kinds of downloads. Yes, I can download using  QNetworkAccessManager but
> then all download will have to be done in either a thread or a process
> because it is time consuming.

How does that matter? Even if the download takes long, becaue the QNAM
API's are async, you will get a notification when a download
completes. You can then use the req url, stored in the QNetworkReply
object you got when you dispatched the request, to figure out which
request got completed. I still don't see a case for a separate
thread/process for just the download part (maybe I'm missing some
info).

Sorry for replying late. Whatever you have suggested above makes sense to me. I will try that out. Thanks for all your help.
>
> How can I use processEvents in my class process app events?

Umm not sure what you meant here. Why do you manually need to call
processEvents? Are you blocking your event loop somewhere or are you
worried that the time-consuming download will block your event loop?
(the download won't block your event loop).

HTH,
-mandeep


>
> Regards,
> Lata
>>
>>
>> -mandeep
>
>
>
>
> --
>
>
> Lata Agrawal
> Senior Developer
> 9699750643
> En Route Media Pvt. Ltd.
>
>
Reply all
Reply to author
Forward
0 new messages