QProcess/Unix: fix close() on invalid file descriptor
Commit 90bc0ad41f9937f9cba801b3166635f6f55e0678 ("QProcess/Unix: add failChildProcessModifier()") added this line that set childStartedPipe so that the failChildProcess() callback had something to write to. But we left it set on exit from QProcessPrivate::startDetached(), which caused the QProcess destructor to try and close it. Noticed when debugging the issue for QTBUG-123083. Pick-to: 6.7.0 Task-number: QTBUG-123083 Change-Id: I6818d78a57394e37857bfffd17bbc41c8400270f Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> (cherry picked from commit 0f56502fb6f062c6d2308198c93412c34525125b) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
a7a2cf8746
commit
a2d67a2671
@ -1290,7 +1290,6 @@ void QProcessPrivate::waitForDeadChild()
|
|||||||
bool QProcessPrivate::startDetached(qint64 *pid)
|
bool QProcessPrivate::startDetached(qint64 *pid)
|
||||||
{
|
{
|
||||||
AutoPipe startedPipe, pidPipe;
|
AutoPipe startedPipe, pidPipe;
|
||||||
childStartedPipe[1] = startedPipe[1];
|
|
||||||
if (!startedPipe || !pidPipe) {
|
if (!startedPipe || !pidPipe) {
|
||||||
setErrorAndEmit(QProcess::FailedToStart, "pipe: "_L1 + qt_error_string(errno));
|
setErrorAndEmit(QProcess::FailedToStart, "pipe: "_L1 + qt_error_string(errno));
|
||||||
return false;
|
return false;
|
||||||
@ -1309,6 +1308,7 @@ bool QProcessPrivate::startDetached(qint64 *pid)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
childStartedPipe[1] = startedPipe[1]; // for failChildProcess()
|
||||||
pid_t childPid = childProcess.doFork([&] {
|
pid_t childPid = childProcess.doFork([&] {
|
||||||
::setsid();
|
::setsid();
|
||||||
|
|
||||||
@ -1323,6 +1323,7 @@ bool QProcessPrivate::startDetached(qint64 *pid)
|
|||||||
qt_safe_write(pidPipe[1], &doubleForkPid, sizeof(pid_t));
|
qt_safe_write(pidPipe[1], &doubleForkPid, sizeof(pid_t));
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
childStartedPipe[1] = -1;
|
||||||
|
|
||||||
int savedErrno = errno;
|
int savedErrno = errno;
|
||||||
closeChannels();
|
closeChannels();
|
||||||
|
@ -1488,6 +1488,9 @@ struct DisableCrashLogger
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
Q_AUTOTEST_EXPORT bool _qprocessUsingVfork() noexcept;
|
||||||
|
QT_END_NAMESPACE
|
||||||
static constexpr char messageFromChildProcess[] = "Message from the child process";
|
static constexpr char messageFromChildProcess[] = "Message from the child process";
|
||||||
static_assert(std::char_traits<char>::length(messageFromChildProcess) <= PIPE_BUF);
|
static_assert(std::char_traits<char>::length(messageFromChildProcess) <= PIPE_BUF);
|
||||||
static void childProcessModifier(int fd)
|
static void childProcessModifier(int fd)
|
||||||
@ -1499,17 +1502,28 @@ static void childProcessModifier(int fd)
|
|||||||
void tst_QProcess::setChildProcessModifier_data()
|
void tst_QProcess::setChildProcessModifier_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<bool>("detached");
|
QTest::addColumn<bool>("detached");
|
||||||
QTest::newRow("normal") << false;
|
QTest::addColumn<bool>("useVfork");
|
||||||
QTest::newRow("detached") << true;
|
QTest::newRow("normal") << false << false;
|
||||||
|
QTest::newRow("detached") << true << false;
|
||||||
|
|
||||||
|
#ifdef QT_BUILD_INTERNAL
|
||||||
|
if (_qprocessUsingVfork()) {
|
||||||
|
QTest::newRow("normal-vfork") << false << true;
|
||||||
|
QTest::newRow("detached-vfork") << true << true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QProcess::setChildProcessModifier()
|
void tst_QProcess::setChildProcessModifier()
|
||||||
{
|
{
|
||||||
QFETCH(bool, detached);
|
QFETCH(bool, detached);
|
||||||
|
QFETCH(bool, useVfork);
|
||||||
int pipes[2] = { -1 , -1 };
|
int pipes[2] = { -1 , -1 };
|
||||||
QVERIFY(qt_safe_pipe(pipes) == 0);
|
QVERIFY(qt_safe_pipe(pipes) == 0);
|
||||||
|
|
||||||
QProcess process;
|
QProcess process;
|
||||||
|
if (useVfork)
|
||||||
|
process.setUnixProcessParameters(QProcess::UnixProcessFlag::UseVFork);
|
||||||
process.setChildProcessModifier([pipes]() {
|
process.setChildProcessModifier([pipes]() {
|
||||||
::childProcessModifier(pipes[1]);
|
::childProcessModifier(pipes[1]);
|
||||||
});
|
});
|
||||||
@ -1542,7 +1556,11 @@ void tst_QProcess::failChildProcessModifier()
|
|||||||
"Implementation detail: the length of the message is limited");
|
"Implementation detail: the length of the message is limited");
|
||||||
|
|
||||||
QFETCH(bool, detached);
|
QFETCH(bool, detached);
|
||||||
|
QFETCH(bool, useVfork);
|
||||||
|
|
||||||
QProcess process;
|
QProcess process;
|
||||||
|
if (useVfork)
|
||||||
|
process.setUnixProcessParameters(QProcess::UnixProcessFlag::UseVFork);
|
||||||
process.setChildProcessModifier([&process]() {
|
process.setChildProcessModifier([&process]() {
|
||||||
process.failChildProcessModifier(failureMsg, EPERM);
|
process.failChildProcessModifier(failureMsg, EPERM);
|
||||||
});
|
});
|
||||||
@ -1651,9 +1669,6 @@ void tst_QProcess::terminateInChildProcessModifier()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
Q_AUTOTEST_EXPORT bool _qprocessUsingVfork() noexcept;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
void tst_QProcess::raiseInChildProcessModifier()
|
void tst_QProcess::raiseInChildProcessModifier()
|
||||||
{
|
{
|
||||||
#ifdef QT_BUILD_INTERNAL
|
#ifdef QT_BUILD_INTERNAL
|
||||||
|
Loading…
x
Reference in New Issue
Block a user