diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2024-03-11 09:55:10 -0700 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2024-03-14 07:24:47 +0000 |
commit | 0df3ff3d7067c5a57e51a49303f5558b48d348de (patch) | |
tree | 01351af9c78e4b58b8c0a2cf5eb5643692f2fda4 | |
parent | 9057431efb886990cf633bbb304d18a1d624fe0e (diff) |
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.
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>
(cherry picked from commit a2d67a2671f8b2ab96d4b458d80972c2bd83b3db)
-rw-r--r-- | src/corelib/io/qprocess_unix.cpp | 3 | ||||
-rw-r--r-- | tests/auto/corelib/io/qprocess/tst_qprocess.cpp | 25 |
2 files changed, 22 insertions, 6 deletions
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index ca65a3c776..fcbce92ade 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -1290,7 +1290,6 @@ void QProcessPrivate::waitForDeadChild() bool QProcessPrivate::startDetached(qint64 *pid) { AutoPipe startedPipe, pidPipe; - childStartedPipe[1] = startedPipe[1]; if (!startedPipe || !pidPipe) { setErrorAndEmit(QProcess::FailedToStart, "pipe: "_L1 + qt_error_string(errno)); return false; @@ -1309,6 +1308,7 @@ bool QProcessPrivate::startDetached(qint64 *pid) return false; } + childStartedPipe[1] = startedPipe[1]; // for failChildProcess() pid_t childPid = childProcess.doFork([&] { ::setsid(); @@ -1323,6 +1323,7 @@ bool QProcessPrivate::startDetached(qint64 *pid) qt_safe_write(pidPipe[1], &doubleForkPid, sizeof(pid_t)); return 0; }); + childStartedPipe[1] = -1; int savedErrno = errno; closeChannels(); diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index 46c25b9067..1056eaa107 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -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_assert(std::char_traits<char>::length(messageFromChildProcess) <= PIPE_BUF); static void childProcessModifier(int fd) @@ -1499,17 +1502,28 @@ static void childProcessModifier(int fd) void tst_QProcess::setChildProcessModifier_data() { QTest::addColumn<bool>("detached"); - QTest::newRow("normal") << false; - QTest::newRow("detached") << true; + QTest::addColumn<bool>("useVfork"); + 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() { QFETCH(bool, detached); + QFETCH(bool, useVfork); int pipes[2] = { -1 , -1 }; QVERIFY(qt_safe_pipe(pipes) == 0); QProcess process; + if (useVfork) + process.setUnixProcessParameters(QProcess::UnixProcessFlag::UseVFork); process.setChildProcessModifier([pipes]() { ::childProcessModifier(pipes[1]); }); @@ -1542,7 +1556,11 @@ void tst_QProcess::failChildProcessModifier() "Implementation detail: the length of the message is limited"); QFETCH(bool, detached); + QFETCH(bool, useVfork); + QProcess process; + if (useVfork) + process.setUnixProcessParameters(QProcess::UnixProcessFlag::UseVFork); process.setChildProcessModifier([&process]() { process.failChildProcessModifier(failureMsg, EPERM); }); @@ -1651,9 +1669,6 @@ void tst_QProcess::terminateInChildProcessModifier() #endif } -QT_BEGIN_NAMESPACE -Q_AUTOTEST_EXPORT bool _qprocessUsingVfork() noexcept; -QT_END_NAMESPACE void tst_QProcess::raiseInChildProcessModifier() { #ifdef QT_BUILD_INTERNAL |