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
comment:2 Changed 15 years ago by
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
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
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
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
Cc: | psmedley added |
---|
comment:8 Changed 15 years ago by
Thanks guys, this is what I came up with after studying kLibc sources as well.
comment:9 Changed 15 years ago by
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
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
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
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
Resolution: | → fixed |
---|---|
Status: | new → closed |
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.