diff options
author | Alex Trotsenko <alex1973tr@gmail.com> | 2020-12-28 19:43:52 +0200 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@gmx.de> | 2020-12-31 12:16:38 +0000 |
commit | 04c34eb7992c88a84b04928985c231c44694ae8f (patch) | |
tree | 3906aa6b84a281787ac6ad081c92c69d8b2e3c05 /src | |
parent | 1fb9c5348e3f7d4dd80e5b924aaca93632c651f9 (diff) |
QProcess: allow merged channels forwarding for detached processes
[ChangeLog][QtCore][QProcess] Added support for QProcess::MergedChannels
mode with startDetached().
Change-Id: I953ad2063322015332269522a297f8e2842e438c
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/io/qprocess.cpp | 9 | ||||
-rw-r--r-- | src/corelib/io/qprocess_p.h | 3 | ||||
-rw-r--r-- | src/corelib/io/qprocess_unix.cpp | 45 | ||||
-rw-r--r-- | src/corelib/io/qprocess_win.cpp | 12 |
4 files changed, 32 insertions, 37 deletions
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 9c6dafd7ef..bd25910976 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -616,7 +616,8 @@ void QProcessPrivate::Channel::clear() process into the standard output channel (\c stdout). The standard error channel (\c stderr) will not receive any data. The standard output and standard error data of the running process - are interleaved. + are interleaved. For detached processes, the merged output of the + running process is forwarded onto the main process. \value ForwardedChannels QProcess forwards the output of the running process onto the main process. Anything the child process @@ -1000,10 +1001,11 @@ bool QProcessPrivate::openChannelsForDetached() return false; // stderr channel. - if (processChannelMode == QProcess::MergedChannels || (stderrChannel.type != Channel::Normal + if (stderrChannel.type != Channel::Normal && (stderrChannel.type != Channel::Redirect || processChannelMode == QProcess::ForwardedChannels - || processChannelMode == QProcess::ForwardedErrorChannel))) { + || processChannelMode == QProcess::ForwardedErrorChannel + || processChannelMode == QProcess::MergedChannels)) { qWarning("QProcess::openChannelsForDetached: Inconsistent stderr channel configuration"); } if (stderrChannel.type == Channel::Redirect && !openChannel(stderrChannel)) @@ -2172,6 +2174,7 @@ void QProcess::startCommand(const QString &command, OpenMode mode) \li setStandardErrorFile() \li setStandardInputFile() \li setStandardOutputFile() + \li setProcessChannelMode(QProcess::MergedChannels) \li setWorkingDirectory() \endlist All other properties of the QProcess object are ignored. diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 3be73f479e..58d68f83cf 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -319,6 +319,9 @@ public: bool openChannels(); bool openChannelsForDetached(); bool openChannel(Channel &channel); +#if defined(Q_OS_UNIX) + void commitChannels(); +#endif void closeChannel(Channel *channel); void closeWriteChannel(); bool tryReadFromChannel(Channel *channel); // obviously, only stdout and stderr diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index f12d92b253..c9ede9c3e9 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -319,6 +319,24 @@ bool QProcessPrivate::openChannel(Channel &channel) } } +void QProcessPrivate::commitChannels() +{ + // copy the stdin socket if asked to (without closing on exec) + if (stdinChannel.pipe[0] != INVALID_Q_PIPE) + qt_safe_dup2(stdinChannel.pipe[0], STDIN_FILENO, 0); + + // copy the stdout and stderr if asked to + if (stdoutChannel.pipe[1] != INVALID_Q_PIPE) + qt_safe_dup2(stdoutChannel.pipe[1], STDOUT_FILENO, 0); + if (stderrChannel.pipe[1] != INVALID_Q_PIPE) { + qt_safe_dup2(stderrChannel.pipe[1], STDERR_FILENO, 0); + } else { + // merge stdout and stderr if asked to + if (processChannelMode == QProcess::MergedChannels) + qt_safe_dup2(STDOUT_FILENO, STDERR_FILENO, 0); + } +} + static char **_q_dupEnvironment(const QProcessEnvironmentPrivate::Map &environment, int *envc) { *envc = 0; @@ -525,20 +543,8 @@ void QProcessPrivate::execChild(const char *workingDir, char **argv, char **envp ChildError error = { 0, {} }; // force zeroing of function[8] - // copy the stdin socket if asked to (without closing on exec) - if (stdinChannel.pipe[0] != INVALID_Q_PIPE) - qt_safe_dup2(stdinChannel.pipe[0], STDIN_FILENO, 0); - - // copy the stdout and stderr if asked to - if (stdoutChannel.pipe[1] != INVALID_Q_PIPE) - qt_safe_dup2(stdoutChannel.pipe[1], STDOUT_FILENO, 0); - if (stderrChannel.pipe[1] != INVALID_Q_PIPE) { - qt_safe_dup2(stderrChannel.pipe[1], STDERR_FILENO, 0); - } else { - // merge stdout and stderr if asked to - if (processChannelMode == QProcess::MergedChannels) - qt_safe_dup2(STDOUT_FILENO, STDERR_FILENO, 0); - } + // Render channels configuration. + commitChannels(); // make sure this fd is closed if execv() succeeds qt_safe_close(childStartedPipe[0]); @@ -901,15 +907,8 @@ bool QProcessPrivate::startDetached(qint64 *pid) if (doubleForkPid == 0) { qt_safe_close(pidPipe[1]); - // copy the stdin socket if asked to (without closing on exec) - if (stdinChannel.type == Channel::Redirect) - qt_safe_dup2(stdinChannel.pipe[0], STDIN_FILENO, 0); - - // copy the stdout and stderr if asked to - if (stdoutChannel.type == Channel::Redirect) - qt_safe_dup2(stdoutChannel.pipe[1], STDOUT_FILENO, 0); - if (stderrChannel.type == Channel::Redirect) - qt_safe_dup2(stderrChannel.pipe[1], STDERR_FILENO, 0); + // Render channels configuration. + commitChannels(); if (!encodedWorkingDirectory.isEmpty()) { if (QT_CHDIR(encodedWorkingDirectory.constData()) == -1) diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index c9223443e2..0ed1f3f428 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -914,17 +914,7 @@ bool QProcessPrivate::startDetached(qint64 *pid) DWORD dwCreationFlags = (GetConsoleWindow() ? 0 : CREATE_NO_WINDOW); dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT; - STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0, - (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - 0, 0, 0, - STARTF_USESTDHANDLES, - 0, 0, 0, - pipeOrStdHandle(stdinChannel.pipe[0], STD_INPUT_HANDLE), - pipeOrStdHandle(stdoutChannel.pipe[1], STD_OUTPUT_HANDLE), - pipeOrStdHandle(stderrChannel.pipe[1], STD_ERROR_HANDLE) - }; - + STARTUPINFOW startupInfo = createStartupInfo(); QProcess::CreateProcessArguments cpargs = { nullptr, reinterpret_cast<wchar_t *>(const_cast<ushort *>(args.utf16())), nullptr, nullptr, true, dwCreationFlags, envPtr, |