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 {
|
||||
// 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
|
||||
// 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
|
||||
// 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 DECLARE_FUNCTIONS
|
||||
|
||||
// like qt_ignore_sigpipe() in qcore_unix_p.h, but vfork-safe
|
||||
static void ignore_sigpipe()
|
||||
// similar to qt_ignore_sigpipe() in qcore_unix_p.h, but vfork-safe
|
||||
static void change_sigpipe(decltype(SIG_DFL) new_handler)
|
||||
{
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sa.sa_handler = new_handler;
|
||||
sigaction(SIGPIPE, &sa, nullptr);
|
||||
}
|
||||
} // 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
|
||||
bool ignore_sigpipe = params.flags.testFlag(QProcess::UnixProcessFlag::IgnoreSigPipe);
|
||||
if (ignore_sigpipe)
|
||||
QtVforkSafe::ignore_sigpipe();
|
||||
QtVforkSafe::change_sigpipe(SIG_IGN);
|
||||
if (params.flags.testFlag(QProcess::UnixProcessFlag::ResetSignalHandlers)) {
|
||||
struct sigaction sa = {};
|
||||
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.
|
||||
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]
|
||||
|
||||
@ -1150,7 +1158,7 @@ bool QProcessPrivate::startDetached(qint64 *pid)
|
||||
}();
|
||||
pid_t childPid = doFork();
|
||||
if (childPid == 0) {
|
||||
QtVforkSafe::ignore_sigpipe(); // reset the signal that we ignored
|
||||
QtVforkSafe::change_sigpipe(SIG_DFL); // reset the signal that we ignored
|
||||
::setsid();
|
||||
|
||||
qt_safe_close(startedPipe[0]);
|
||||
|
@ -1594,6 +1594,10 @@ void tst_QProcess::unixProcessParameters()
|
||||
process.start();
|
||||
QVERIFY2(process.waitForStarted(5000), qPrintable(process.errorString()));
|
||||
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.readAll(), QString());
|
||||
QCOMPARE(process.exitCode(), 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user