Opened 15 years ago

Closed 15 years ago

#69 closed defect (fixed)

QProcess cannot start process

Reported by: Dmitry A. Kuminov Owned by:
Priority: blocker Milestone: Qt Beta 2
Component: QtCore Version: 4.5.1 Beta 1
Severity: Keywords:
Cc: psmedley

Description

The following simple program:

	qDebug() << "Starting...";
	QProcess proc;    
	proc.start("cmd.exe");
	qDebug() << "Waiting for finished...";
	proc.waitForFinished();
	qDebug() << "DONE";

terminates immediately with the following output:

Starting...
Waiting for finished...
DONE
QProcess: Destroyed while process is still running.

Apparently, nothing is started.

Change History (13)

comment:1 by Dmitry A. Kuminov, 15 years ago

I'm wrong, it works. At least if I change "cmd.exe" to "cmd.exe /c dir >aaa" I get the current directory's listing in "aaa".

I will try some more sophisticated example.

comment:2 by Dmitry A. Kuminov, 15 years ago

OK, it generally works. I successfully started view.exe and other applications. However, it seems that spawnvpe() (internally used by Qt on OS/2) cannot start some particular binaries, for example, e.exe from eComStation 2.0: spawnvpe() returns a pid of 0 (which means no error, but the pid is of course invalid) and nothing happens. Doing "cmd /c e.exe" works. I will have to investigate it (probably later, after other tasks are done).

comment:3 by Dmitry A. Kuminov, 15 years ago

Another problem is that QProcess cannot wait for the process to finish: select() on pipe handles always returns "-1 Invalid argument". I have no idea why, I've checked the arguments a hundred times.

comment:4 by Dmitry A. Kuminov, 15 years ago

Even in this simple (non-Qt) program:

#include <sys/process.h>
#include <sys/select.h>

int main()
{
    int fdin = fileno(stdin);
    fd_set fdwrite;
    FD_ZERO(&fdwrite);
    FD_SET(fdin, &fdwrite);
    int rc = ::select(fdin + 1, NULL, &fdwrite, NULL, NULL);
    return 0;
}

select() returns -1. Grrr.

comment:5 by psmedley, 15 years ago

In libc, select() can only be used on socket handles. It cannot be used on pipe()

You can however use socketpair() instead of pipe() which will achieve the same thing, and you can select() on it.

I use this workaround for CUPS.

comment:6 by psmedley, 15 years ago

Cc: psmedley added

comment:7 by Silvan Scherrer, 15 years ago

also in samba i had to user socketpair() instead of pipe()

comment:8 by Dmitry A. Kuminov, 15 years ago

Thanks guys, this is what I came up with after studying kLibc sources as well.

comment:9 by Dmitry A. Kuminov, 15 years ago

Ok, socketpair() seems to solve the select() failure but QProcess::waitForFinished() still doesn't work as designed. Investigating.

comment:10 by Dmitry A. Kuminov, 15 years ago

I must have forgotten that spawn* in kLIBC only implements P_WAIT, P_NOWAIT and P_OVERLAY modes (it uses DosExecPgm for them). This means that processes of different type cannot be created with spawn* at the moment (and it explains why we can't spawn PM programs from non-PM ones as in case of e.exe).

The question is what to do. We may detect cases when the target process would have a different process type and prepend 'cmd /c' to make sure it can be started. I tend to do it like this because an equivalent Qt console program on Windows can easily start a GUI application such as notepad.exe w/o prepending it with 'cmd /c'.

comment:11 by Silvan Scherrer, 15 years ago

i guess it would be best to do like that, as to add cmd /c in such qt app's seems a bit strange to me. the question is more is it easy to detect if a app needs that?

comment:12 by Dmitry A. Kuminov, 15 years ago

Yes, we may detect this using DosQueryAppType.

There is another problem: non-kLIBC child applications (for example, cmd.exe) cannot write to (and possibly read from) the redirected standard streams we prepare for them using socketpair() and dup2(). Interesting that after dup2(), the output of the child application disappears from the console but it doesn't appear at the other end of the socket pair. I can't find a good explanation for that. For sure, this is because the kLIBC inheritance processor doesn't get executed in a non-kLIBC child, but I would expect stdin/err/out redirection to work anyway (aren't standard stream's kLIBC file handles backed up by real file handles?).

In any case, it seems that we will have to forget about socketpair() and dup2() and use native pipes for redirection as in Qt3. This is a lot of work...

comment:13 by Dmitry A. Kuminov, 15 years ago

Resolution: fixed
Status: newclosed

I've committed a fix that makes redirection work for kLIBC-based processes.

For the rest I created three other tickets (#70, #71 and #72) since I don't want to delay Beta 2 for too long -- these problems don't look like stoppers for the beta so far.

Note: See TracTickets for help on using tickets.