QProcess/Unix: fix setting SIGPIPE to SIG_IGN where SIG_DFL was intended
And take the opportunity to clarify what the QtVforkSafe namespace is doing. Amends commit e71c226d6f188abd811b28d3cb7529343f52d61f. Change-Id: I443cf0c8a76243eead33fffd1767f3fa390a7cdd Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de> (cherry picked from commit c4a0a76deca0bc5082fb561004bc0d29a8de9978) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
081dd8d7f0
commit
12b43d3902
@ -109,7 +109,15 @@ QProcessEnvironment QProcessEnvironment::systemEnvironment()
|
|||||||
namespace QtVforkSafe {
|
namespace QtVforkSafe {
|
||||||
// Certain libc functions we need to call in the child process scenario aren't
|
// Certain libc functions we need to call in the child process scenario aren't
|
||||||
// safe under vfork() because they do more than just place the system call to
|
// safe under vfork() because they do more than just place the system call to
|
||||||
// the kernel and set errno on return. Those are:
|
// the kernel and set errno on return. For those, we'll create a function
|
||||||
|
// pointer like:
|
||||||
|
// static constexpr auto foobar = __libc_foobar;
|
||||||
|
// while for all other OSes, it'll be
|
||||||
|
// using ::foobar;
|
||||||
|
// allowing the code for the child side of the vfork to simply use
|
||||||
|
// QtVforkSafe::foobar(args);
|
||||||
|
//
|
||||||
|
// Currently known issues are:
|
||||||
//
|
//
|
||||||
// - FreeBSD's libthr sigaction() wrapper locks a rwlock
|
// - FreeBSD's libthr sigaction() wrapper locks a rwlock
|
||||||
// https://github.com/freebsd/freebsd-src/blob/8dad5ece49479ba6cdcd5bb4c2799bbd61add3e6/lib/libthr/thread/thr_sig.c#L575-L641
|
// https://github.com/freebsd/freebsd-src/blob/8dad5ece49479ba6cdcd5bb4c2799bbd61add3e6/lib/libthr/thread/thr_sig.c#L575-L641
|
||||||
@ -142,11 +150,11 @@ DECLARE_FUNCTIONS(sigaction)
|
|||||||
#undef LIBC_PREFIX
|
#undef LIBC_PREFIX
|
||||||
#undef DECLARE_FUNCTIONS
|
#undef DECLARE_FUNCTIONS
|
||||||
|
|
||||||
// like qt_ignore_sigpipe() in qcore_unix_p.h, but vfork-safe
|
// similar to qt_ignore_sigpipe() in qcore_unix_p.h, but vfork-safe
|
||||||
static void ignore_sigpipe()
|
static void change_sigpipe(decltype(SIG_DFL) new_handler)
|
||||||
{
|
{
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
sa.sa_handler = SIG_IGN;
|
sa.sa_handler = new_handler;
|
||||||
sigaction(SIGPIPE, &sa, nullptr);
|
sigaction(SIGPIPE, &sa, nullptr);
|
||||||
}
|
}
|
||||||
} // namespace QtVforkSafe
|
} // namespace QtVforkSafe
|
||||||
@ -653,7 +661,7 @@ static void applyProcessParameters(const QProcess::UnixProcessParameters ¶ms
|
|||||||
// We don't expect signal() to fail, so we ignore its return value
|
// We don't expect signal() to fail, so we ignore its return value
|
||||||
bool ignore_sigpipe = params.flags.testFlag(QProcess::UnixProcessFlag::IgnoreSigPipe);
|
bool ignore_sigpipe = params.flags.testFlag(QProcess::UnixProcessFlag::IgnoreSigPipe);
|
||||||
if (ignore_sigpipe)
|
if (ignore_sigpipe)
|
||||||
QtVforkSafe::ignore_sigpipe();
|
QtVforkSafe::change_sigpipe(SIG_IGN);
|
||||||
if (params.flags.testFlag(QProcess::UnixProcessFlag::ResetSignalHandlers)) {
|
if (params.flags.testFlag(QProcess::UnixProcessFlag::ResetSignalHandlers)) {
|
||||||
struct sigaction sa = {};
|
struct sigaction sa = {};
|
||||||
sa.sa_handler = SIG_DFL;
|
sa.sa_handler = SIG_DFL;
|
||||||
@ -739,7 +747,7 @@ static const char *doExecChild(char **argv, char **envp, int workingDirFd,
|
|||||||
// still sharing memory with the parent process.
|
// still sharing memory with the parent process.
|
||||||
void QProcessPrivate::execChild(int workingDir, char **argv, char **envp) const noexcept
|
void QProcessPrivate::execChild(int workingDir, char **argv, char **envp) const noexcept
|
||||||
{
|
{
|
||||||
QtVforkSafe::ignore_sigpipe(); // reset the signal that we ignored
|
QtVforkSafe::change_sigpipe(SIG_DFL); // reset the signal that we ignored
|
||||||
|
|
||||||
ChildError error = { 0, {} }; // force zeroing of function[8]
|
ChildError error = { 0, {} }; // force zeroing of function[8]
|
||||||
|
|
||||||
@ -1150,7 +1158,7 @@ bool QProcessPrivate::startDetached(qint64 *pid)
|
|||||||
}();
|
}();
|
||||||
pid_t childPid = doFork();
|
pid_t childPid = doFork();
|
||||||
if (childPid == 0) {
|
if (childPid == 0) {
|
||||||
QtVforkSafe::ignore_sigpipe(); // reset the signal that we ignored
|
QtVforkSafe::change_sigpipe(SIG_DFL); // reset the signal that we ignored
|
||||||
::setsid();
|
::setsid();
|
||||||
|
|
||||||
qt_safe_close(startedPipe[0]);
|
qt_safe_close(startedPipe[0]);
|
||||||
|
@ -1594,6 +1594,10 @@ void tst_QProcess::unixProcessParameters()
|
|||||||
process.start();
|
process.start();
|
||||||
QVERIFY2(process.waitForStarted(5000), qPrintable(process.errorString()));
|
QVERIFY2(process.waitForStarted(5000), qPrintable(process.errorString()));
|
||||||
QVERIFY(process.waitForFinished(5000));
|
QVERIFY(process.waitForFinished(5000));
|
||||||
|
|
||||||
|
#ifdef Q_OS_QNX
|
||||||
|
QEXPECT_FAIL("ignore-sigpipe", "QTBUG-114720: flag is taking no effect", Abort);
|
||||||
|
#endif
|
||||||
QCOMPARE(process.readAllStandardError(), QString());
|
QCOMPARE(process.readAllStandardError(), QString());
|
||||||
QCOMPARE(process.readAll(), QString());
|
QCOMPARE(process.readAll(), QString());
|
||||||
QCOMPARE(process.exitCode(), 0);
|
QCOMPARE(process.exitCode(), 0);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user