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(). Change-Id: Ic90d8429a0eb4837971dfffd1664e825ffcb923e Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de> (cherry picked from commit 73a04edce151b21ea5d07494603c0317716e99d9) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
3961b82e6c
commit
64c47d7f61
@ -2132,11 +2132,12 @@ void QProcess::startCommand(const QString &command, OpenMode mode)
|
|||||||
temporarily freeze.
|
temporarily freeze.
|
||||||
|
|
||||||
If the function is successful then *\a pid is set to the process identifier
|
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
|
of the started process; otherwise, it's set to -1. Note that the child
|
||||||
may become invalid without notice. Furthermore, after the child process
|
process may exit and the PID may become invalid without notice.
|
||||||
exits, the same PID may be recycled and used by a completely different
|
Furthermore, after the child process exits, the same PID may be recycled
|
||||||
process. User code should be careful when using this variable, especially
|
and used by a completely different process. User code should be careful
|
||||||
if one intends to forcibly terminate the process by operating system means.
|
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():
|
Only the following property setters are supported by startDetached():
|
||||||
\list
|
\list
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2020 The Qt Company Ltd.
|
||||||
** Copyright (C) 2016 Intel Corporation.
|
** Copyright (C) 2021 Intel Corporation.
|
||||||
|
** Copyright (C) 2021 Alex Trotsenko.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the QtCore module of the Qt Toolkit.
|
** 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
|
// To catch the startup of the child
|
||||||
int startedPipe[2];
|
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;
|
return false;
|
||||||
|
}
|
||||||
// To communicate the pid of the child
|
// To communicate the pid of the child
|
||||||
int pidPipe[2];
|
int pidPipe[2];
|
||||||
if (qt_safe_pipe(pidPipe) != 0) {
|
if (qt_safe_pipe(pidPipe) != 0) {
|
||||||
|
setErrorAndEmit(QProcess::FailedToStart, QLatin1String("pipe: ") + qt_error_string(errno));
|
||||||
qt_safe_close(startedPipe[0]);
|
qt_safe_close(startedPipe[0]);
|
||||||
qt_safe_close(startedPipe[1]);
|
qt_safe_close(startedPipe[1]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!openChannelsForDetached()) {
|
if (!openChannelsForDetached()) {
|
||||||
|
// openChannel sets the error string
|
||||||
closeChannel(&stdinChannel);
|
closeChannel(&stdinChannel);
|
||||||
closeChannel(&stdoutChannel);
|
closeChannel(&stdoutChannel);
|
||||||
closeChannel(&stderrChannel);
|
closeChannel(&stderrChannel);
|
||||||
@ -981,6 +986,7 @@ bool QProcessPrivate::startDetached(qint64 *pid)
|
|||||||
::_exit(1);
|
::_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int savedErrno = errno;
|
||||||
closeChannel(&stdinChannel);
|
closeChannel(&stdinChannel);
|
||||||
closeChannel(&stdoutChannel);
|
closeChannel(&stdoutChannel);
|
||||||
closeChannel(&stderrChannel);
|
closeChannel(&stderrChannel);
|
||||||
@ -990,6 +996,7 @@ bool QProcessPrivate::startDetached(qint64 *pid)
|
|||||||
if (childPid == -1) {
|
if (childPid == -1) {
|
||||||
qt_safe_close(startedPipe[0]);
|
qt_safe_close(startedPipe[0]);
|
||||||
qt_safe_close(pidPipe[0]);
|
qt_safe_close(pidPipe[0]);
|
||||||
|
setErrorAndEmit(QProcess::FailedToStart, QLatin1String("fork: ") + qt_error_string(savedErrno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -998,14 +1005,17 @@ bool QProcessPrivate::startDetached(qint64 *pid)
|
|||||||
int result;
|
int result;
|
||||||
qt_safe_close(startedPipe[0]);
|
qt_safe_close(startedPipe[0]);
|
||||||
qt_safe_waitpid(childPid, &result, 0);
|
qt_safe_waitpid(childPid, &result, 0);
|
||||||
|
|
||||||
bool success = (startResult != -1 && reply == '\0');
|
bool success = (startResult != -1 && reply == '\0');
|
||||||
if (success && pid) {
|
if (success && pid) {
|
||||||
pid_t actualPid = 0;
|
pid_t actualPid;
|
||||||
if (qt_safe_read(pidPipe[0], (char *)&actualPid, sizeof(pid_t)) == sizeof(pid_t)) {
|
if (qt_safe_read(pidPipe[0], &actualPid, sizeof(pid_t)) != sizeof(pid_t))
|
||||||
*pid = actualPid;
|
actualPid = 0;
|
||||||
} else {
|
*pid = actualPid;
|
||||||
*pid = 0;
|
} else if (!success) {
|
||||||
}
|
if (pid)
|
||||||
|
*pid = -1;
|
||||||
|
setErrorAndEmit(QProcess::FailedToStart);
|
||||||
}
|
}
|
||||||
qt_safe_close(pidPipe[0]);
|
qt_safe_close(pidPipe[0]);
|
||||||
return success;
|
return success;
|
||||||
|
@ -869,6 +869,7 @@ bool QProcessPrivate::startDetached(qint64 *pid)
|
|||||||
static const DWORD errorElevationRequired = 740;
|
static const DWORD errorElevationRequired = 740;
|
||||||
|
|
||||||
if (!openChannelsForDetached()) {
|
if (!openChannelsForDetached()) {
|
||||||
|
// openChannel sets the error string
|
||||||
closeChannel(&stdinChannel);
|
closeChannel(&stdinChannel);
|
||||||
closeChannel(&stdoutChannel);
|
closeChannel(&stdoutChannel);
|
||||||
closeChannel(&stderrChannel);
|
closeChannel(&stderrChannel);
|
||||||
@ -913,6 +914,11 @@ bool QProcessPrivate::startDetached(qint64 *pid)
|
|||||||
success = startDetachedUacPrompt(program, arguments, nativeArguments,
|
success = startDetachedUacPrompt(program, arguments, nativeArguments,
|
||||||
workingDirectory, pid);
|
workingDirectory, pid);
|
||||||
}
|
}
|
||||||
|
if (!success) {
|
||||||
|
if (pid)
|
||||||
|
*pid = -1;
|
||||||
|
setErrorAndEmit(QProcess::FailedToStart);
|
||||||
|
}
|
||||||
|
|
||||||
closeChannel(&stdinChannel);
|
closeChannel(&stdinChannel);
|
||||||
closeChannel(&stdoutChannel);
|
closeChannel(&stdoutChannel);
|
||||||
|
@ -2279,6 +2279,8 @@ void tst_QProcess::detachedSetNonExistentWorkingDirectory()
|
|||||||
qint64 pid = -1;
|
qint64 pid = -1;
|
||||||
QVERIFY(!process.startDetached(&pid));
|
QVERIFY(!process.startDetached(&pid));
|
||||||
QCOMPARE(pid, -1);
|
QCOMPARE(pid, -1);
|
||||||
|
QCOMPARE(process.error(), QProcess::FailedToStart);
|
||||||
|
QVERIFY(process.errorString() != "Unknown error");
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QProcess::startFinishStartFinish()
|
void tst_QProcess::startFinishStartFinish()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user