Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QProcess finished() returns before completion on MACOSX



  • Hi All,
    I have a use-case wherein one process calls another process and waits for the results from the second process. I'm using the QProcess API's to do the same. The problem that I'm observing is that the finished() signal is received even before the called process is done, leading to the calling process trying to process non-existent/wrong output. I attach below a snippet of code trying to capture the idiom of the call flow:

    QProcess m_process = new QProcess()//Creates a handle to a QProcess object.
    m_process->setProgram(“<Location of folder>/calledApp”);//Sets the application to be executed.
    connect(m_process, SIGNAL(finished(int)), this, SLOT(onProcessFinished(int)));
    m_process->start();
    if(m_process->waitForStarted())
    {
    for(int i= 0; i<largevalue;i++)
    {
    if(m_process->waitForFinished(100))//100 ms timeout.
    {
    break;
    }
    }
    if(m_process->state() == QProcess::Running ) {
    //print an error.
    }
    }

    The problem is waitForFinished() returns true and the subsequent condition checking for the state of the process returns false, even while the process is still running. This problem doesn't seem to exist on Windows, where waitForFinished() returns only after the called application completes. I'm seriously baffled by this problem. Could someone please help me on this? By the way, I'm running Qt 5.7.1



  • @shivt1190

    I know nothing about MacOS! But if this were a permanent problem under that OS I would expect we would have heard about it, and the Qt docs would say so.

    Firstly, although I'm not saying it will apply in this case given that you say the process continues to run, you should hook onto http://doc.qt.io/qt-5/qprocess.html#errorOccurred signal, just in case....

    Secondly, not all subprocesses are waitable in the sense you mean. Under Windows, and to a lesser extent Linux, "desktop" processes will return "finished" immediately after they are spawned, and you cannot wait for actual completion. This would apply to running, say, Notepad, or calling ShellExecute to run a process. So, does your finding apply to any/all subprocesses, or to some particular one you are trying?



  • Hi,
    Thanks for the quick response. Regarding your second point, it applies both to a particular process I'm running as well as a simple Hello World program I wrote, which was why I brought this question to the Qt forum rather than contact the owner of the application I'm having problems trying to spawn.

    What you say about Windows applications returning "finished" immediately after starting contradicts my observation. However, assuming what you say of Notepad applies to my application, how do you recommend we check for completion? I even tried passing -1 to waitForFinished() rather than a finite duration, but there was no change in behavior.

    Thanks a lot,
    Regards,
    Shiv.



  • @shivt1190
    Does what you call "a simple Hello World program" mean just using stdout (e.g. printf), or is it some kind of MacOS GUI app? Assuming the former, have you done whatever it is to mark/link the app as some kind of "console" app, whatever that entails under MacOS? If it is a simple command line printf("Hello world");, how do you know:

    The problem is waitForFinished() returns true and the subsequent condition checking for the state of the process returns false, even while the process is still running

    ? i.e. how do you know that the sub-process is still running at the time waitForFinished() is hit?

    I still maintain/suggest that all should be working OK under MacOS, else others would report that this completely fundamental code is broken....



  • @JonB

    My "Hello World program" is just a printf("Hello World"), and my expectation is that "Hello World" should be printed to the console before the "finished" signal is received. Instead I see nothing at all on the screen except some prints indicating the "finished" signal has been received. I'm not aware what needs to be done to mark the app as a "console" app.

    Regarding your point about everything being okay with Qt 5.7.1 on MAC, do you see anything obviously wrong in the code snippet I've included? Is there something that needs to be tweaked on a Unix-based system maybe? Or should a different function be used?

    Thanks,
    Regards,
    Shiv.



  • @shivt1190

    My "Hello World program" is just a printf("Hello World"), and my expectation is that "Hello World" should be printed to the console before the "finished" signal is received.

    Your expectation is incorrect (at least "-ish"). There is not reason why they should not appear/arrive at just about the same time.

    Instead I see nothing at all on the screen except some prints indicating the "finished" signal has been received.

    Your expectation is definitely wrong here, and the behaviour is correct. When spawning a QProcess::start(), the point is that the parent (your app) has stdin/stdout/stderr attached into itself, not to some console/window. It is then its job to decide what to do what, say, the output. (You could use QProcess::ForwardedChannels (http://doc.qt.io/qt-5/qprocess.html#ProcessChannelMode-enum) to achieve what you think should be happening. You need to read all about QProcess "channels" to understand this.)

    Given the above, I am still dubious about your claim:

    The problem that I'm observing is that the finished() signal is received even before the called process is done

    Try the following "Hello World" variant (skeleton, or equivalent):

    void main(void)
    {
        printf("Hello world\n");
        sleep(10);
    }
    

    (For this test you may also omit the printf, as that's not what we're trying to test.)

    Now, all we care about is that a m_process->waitForFinished() (no 100ms argument), or a slot for the finished signal, should be seen to arrive 10 seconds after the process is spawned, and not immediately; it does not arrive before the process has exited. Provided it does indeed behave like that, whatever your issue with some particular app might be, there is no problem with waitForFinished in this case. I suggest you begin by verifying this....



  • @JonB said in QProcess finished() returns before completion on MACOSX:

    printf("Hello world\n");
    

    Thanks a lot for your input. I tried what you said, and yes, the finished signal is indeed received 10 seconds later. Looks like I'll have to take my problem elsewhere.



  • @shivt1190
    OK, so at least we have confirmed that the "wait-for-finished" principle does work on a small example under MacOS, as expected!

    I'm still unsure how you're testing/just what you're seeing for your the actual app you're interested in, and therefore whether you do have a Qt issue or something else.

    There are two things going on here: capturing the output from your sub-processes if that is what you want to do and waiting for the sub-process to finish. You never showed your code for, say:

    leading to the calling process trying to process non-existent/wrong output.

    I ask again: in the case of your problematic sub-process, precisely how do you see your:

    The problem that I'm observing is that the finished() signal is received even before the called process is done

    ? If this is to do with you not having received its output by the time it closes, say so, because your code as-is is not going to receive output... OTOH, if you have (some other way) of reliably discerning that the process continues to be running after the finished signal has been delivered, then you have a different problem...



  • @JonB
    "The problem that I'm observing is that the finished() signal is received even before the called process is done" . The process I'm calling is a GUI and once its done it writes its output to a file. The calling process then processes this file and produces some more output. I can visually see the called process doing something, in terms of executing a script that I provided to it as input. The way I know that the output wasn't created is the absence of the file.



  • @shivt1190

    The process I'm calling is a GUI

    Yes, that's why I said earlier there can be problems waiting for a GUI to finish, depending on how it is written. In some shape or form it does sound like this is returning "finished" immediately to the caller, when it (or a further sub-process, perhaps) is still running.

    I think at this point you should indeed contact the author if you say you can do that.


  • Lifetime Qt Champion

    @shivt1190 What happens if you start this GUI app directly from a terminal (without & character after app name)? Is your terminal then blocked or can you continue to use it?



  • @jsulm (Not knowing about MacOS, I didn't think it had things like a Linux command-line terminal! :) )


  • Moderators

    @JonB you would be surpised about the similarities between MacOS and Linux,
    MacOS has a terminal, its even called terminal, a packet manager etc. and commands are pretty similar as well


  • Lifetime Qt Champion

    @JonB MacOS is a certified UNIX, Linux is not :-)


Log in to reply