summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qprocess_win.cpp
diff options
context:
space:
mode:
authorAlex Trotsenko <alex1973tr@gmail.com>2021-01-05 18:59:40 +0200
committerOswald Buddenhagen <oswald.buddenhagen@gmx.de>2021-01-09 13:15:54 +0000
commit6a6d12ea4b90d24839f13b92237dbc8cce5eaf9d (patch)
tree382a1e3647d41fe1f211aaa1e26d76620af0ccd6 /src/corelib/io/qprocess_win.cpp
parent05706bd2b005dd159be34107cc43c92e7f12eb35 (diff)
Split QProcessPrivate::_q_processDied()
The completion of the child process can take place asynchronously or in one of the waitFor...() functions. In both cases, we used the same handler (_q_processDied()), which caused several problems: a. technically, waitForReadyRead() should have taken into account the result of the calls to _q_canRead...() slots inside the _q_processDied() function: - the user calls waitForReadyRead(); - forkfd descriptor becomes signaled, while a grandchild process is still alive; - as readyRead() signal has not been emitted, _q_processDied() is called; - the grandchild process writes to stdout pipe; - now data arrives, and _q_processDied() will collect it, but won't report it. b. we had a bug with recursions on Unix: - death notification comes asynchronously; - waitForDeadChild() closes forkfd; - _q_canRead...() emits readyRead(); - a slot connected to readyRead() calls waitForFinished(); - waitForFinished() hangs (forkfd == -1). c. for blocking functions, drainOutputPipes() was called twice on Windows. By introducing a new processFinished() function, we leave the read operations in the _q_processDied() slot, while the process completion code is guaranteed to run only once. Change-Id: I5f9d09bc68a058169de4d9e490b48fc0b35e94cd Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Diffstat (limited to 'src/corelib/io/qprocess_win.cpp')
-rw-r--r--src/corelib/io/qprocess_win.cpp8
1 files changed, 5 insertions, 3 deletions
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 6ab854de16..2a5b8fd4fd 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -685,7 +685,7 @@ bool QProcessPrivate::waitForReadyRead(const QDeadlineTimer &deadline)
if (WaitForSingleObjectEx(pid->hProcess, 0, false) == WAIT_OBJECT_0) {
bool readyReadEmitted = drainOutputPipes();
if (pid)
- _q_processDied();
+ processFinished();
return readyReadEmitted;
}
@@ -743,7 +743,9 @@ bool QProcessPrivate::waitForBytesWritten(const QDeadlineTimer &deadline)
// Wait for the process to signal any change in its state,
// such as incoming data, or if the process died.
if (WaitForSingleObjectEx(pid->hProcess, 0, false) == WAIT_OBJECT_0) {
- _q_processDied();
+ drainOutputPipes();
+ if (pid)
+ processFinished();
return false;
}
@@ -782,7 +784,7 @@ bool QProcessPrivate::waitForFinished(const QDeadlineTimer &deadline)
if (WaitForSingleObject(pid->hProcess, timer.nextSleepTime()) == WAIT_OBJECT_0) {
drainOutputPipes();
if (pid)
- _q_processDied();
+ processFinished();
return true;
}