From 73a04edce151b21ea5d07494603c0317716e99d9 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 18 Feb 2021 09:36:56 -0800 Subject: QProcess::startDetached: set the error condition on failure to start And set *pid to -1. [ChangeLog][QtCore][QProcess] If a startDetached() fails to start the target application, the QProcess object should now have a proper error string in errorString(). Pick-to: 6.1 Change-Id: Ic90d8429a0eb4837971dfffd1664e825ffcb923e Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess.cpp | 11 ++++++----- src/corelib/io/qprocess_unix.cpp | 28 +++++++++++++++++++--------- src/corelib/io/qprocess_win.cpp | 6 ++++++ 3 files changed, 31 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 2462d829a0..f03fc067cf 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -2132,11 +2132,12 @@ void QProcess::startCommand(const QString &command, OpenMode mode) temporarily freeze. If the function is successful then *\a pid is set to the process identifier - of the started process. Note that the child process may exit and the PID - may become invalid without notice. Furthermore, after the child process - exits, the same PID may be recycled and used by a completely different - process. User code should be careful when using this variable, especially - if one intends to forcibly terminate the process by operating system means. + of the started process; otherwise, it's set to -1. Note that the child + process may exit and the PID may become invalid without notice. + Furthermore, after the child process exits, the same PID may be recycled + and used by a completely different process. User code should be careful + when using this variable, especially if one intends to forcibly terminate + the process by operating system means. Only the following property setters are supported by startDetached(): \list diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index b6757e5b79..1e74cfff60 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -1,7 +1,8 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 Intel Corporation. +** Copyright (C) 2021 Alex Trotsenko. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -883,17 +884,21 @@ bool QProcessPrivate::startDetached(qint64 *pid) // To catch the startup of the child int startedPipe[2]; - if (qt_safe_pipe(startedPipe) != 0) + if (qt_safe_pipe(startedPipe) != 0) { + setErrorAndEmit(QProcess::FailedToStart, QLatin1String("pipe: ") + qt_error_string(errno)); return false; + } // To communicate the pid of the child int pidPipe[2]; if (qt_safe_pipe(pidPipe) != 0) { + setErrorAndEmit(QProcess::FailedToStart, QLatin1String("pipe: ") + qt_error_string(errno)); qt_safe_close(startedPipe[0]); qt_safe_close(startedPipe[1]); return false; } if (!openChannelsForDetached()) { + // openChannel sets the error string closeChannel(&stdinChannel); closeChannel(&stdoutChannel); closeChannel(&stderrChannel); @@ -981,6 +986,7 @@ bool QProcessPrivate::startDetached(qint64 *pid) ::_exit(1); } + int savedErrno = errno; closeChannel(&stdinChannel); closeChannel(&stdoutChannel); closeChannel(&stderrChannel); @@ -990,6 +996,7 @@ bool QProcessPrivate::startDetached(qint64 *pid) if (childPid == -1) { qt_safe_close(startedPipe[0]); qt_safe_close(pidPipe[0]); + setErrorAndEmit(QProcess::FailedToStart, QLatin1String("fork: ") + qt_error_string(savedErrno)); return false; } @@ -998,14 +1005,17 @@ bool QProcessPrivate::startDetached(qint64 *pid) int result; qt_safe_close(startedPipe[0]); qt_safe_waitpid(childPid, &result, 0); + bool success = (startResult != -1 && reply == '\0'); if (success && pid) { - pid_t actualPid = 0; - if (qt_safe_read(pidPipe[0], (char *)&actualPid, sizeof(pid_t)) == sizeof(pid_t)) { - *pid = actualPid; - } else { - *pid = 0; - } + pid_t actualPid; + if (qt_safe_read(pidPipe[0], &actualPid, sizeof(pid_t)) != sizeof(pid_t)) + actualPid = 0; + *pid = actualPid; + } else if (!success) { + if (pid) + *pid = -1; + setErrorAndEmit(QProcess::FailedToStart); } qt_safe_close(pidPipe[0]); return success; diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index dc8c50127d..0088284d2d 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -869,6 +869,7 @@ bool QProcessPrivate::startDetached(qint64 *pid) static const DWORD errorElevationRequired = 740; if (!openChannelsForDetached()) { + // openChannel sets the error string closeChannel(&stdinChannel); closeChannel(&stdoutChannel); closeChannel(&stderrChannel); @@ -913,6 +914,11 @@ bool QProcessPrivate::startDetached(qint64 *pid) success = startDetachedUacPrompt(program, arguments, nativeArguments, workingDirectory, pid); } + if (!success) { + if (pid) + *pid = -1; + setErrorAndEmit(QProcess::FailedToStart); + } closeChannel(&stdinChannel); closeChannel(&stdoutChannel); -- cgit v1.2.3