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 Changed 15 years ago by Dmitry A. Kuminov

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 Changed 15 years ago by Dmitry A. Kuminov

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 Changed 15 years ago by Dmitry A. Kuminov

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 Changed 15 years ago by Dmitry A. Kuminov

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 Changed 15 years ago by psmedley

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 Changed 15 years ago by psmedley

Cc: psmedley added

comment:7 Changed 15 years ago by Silvan Scherrer

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

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

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

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

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

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

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 Changed 15 years ago by Silvan Scherrer

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 Changed 15 years ago by Dmitry A. Kuminov

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 Changed 15 years ago by Dmitry A. Kuminov

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.