summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlex Trotsenko <alex1973tr@gmail.com>2020-12-28 19:43:52 +0200
committerOswald Buddenhagen <oswald.buddenhagen@gmx.de>2020-12-31 12:16:38 +0000
commit04c34eb7992c88a84b04928985c231c44694ae8f (patch)
tree3906aa6b84a281787ac6ad081c92c69d8b2e3c05 /src
parent1fb9c5348e3f7d4dd80e5b924aaca93632c651f9 (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.cpp9
-rw-r--r--src/corelib/io/qprocess_p.h3
-rw-r--r--src/corelib/io/qprocess_unix.cpp45
-rw-r--r--src/corelib/io/qprocess_win.cpp12
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,