forkfd: Make sure we handle SIGPIPE too

We can't depend on the application/library ignoring the signal for us,
so we do it. O_NOSIGPIPE exists on the BSDs and I'll add it to Linux. If
it isn't supported, then we need to ignore SIGPIPE globally.

Change-Id: I25d85d86649448d5b2b3fffd1450f6afeaea8b18
Reviewed-by: Ralf Nolden <nolden@kde.org>
Reviewed-by: Rafael Roquetto <rafael.roquetto@kdab.com>
This commit is contained in:
Thiago Macieira 2016-05-22 11:18:34 -07:00
parent 3cae115d6d
commit cf6a2e9617

View File

@ -410,6 +410,26 @@ chain_handler:
old_sigaction.sa_handler(signum);
}
static void ignore_sigpipe()
{
#ifdef O_NOSIGPIPE
static ffd_atomic_int done = FFD_ATOMIC_INIT(0);
if (ffd_atomic_load(&done, FFD_ATOMIC_RELAXED))
return;
#endif
struct sigaction action;
memset(&action, 0, sizeof action);
sigemptyset(&action.sa_mask);
action.sa_handler = SIG_IGN;
action.sa_flags = 0;
sigaction(SIGPIPE, &action, NULL);
#ifdef O_NOSIGPIPE
ffd_atomic_store(&done, 1, FFD_ATOMIC_RELAXED);
#endif
}
static void forkfd_initialize()
{
#if defined(HAVE_BROKEN_WAITID)
@ -446,6 +466,11 @@ static void forkfd_initialize()
*/
sigaction(SIGCHLD, &action, &old_sigaction);
#ifndef O_NOSIGPIPE
/* disable SIGPIPE too */
ignore_sigpipe();
#endif
#ifndef __GNUC__
atexit(cleanup);
#endif
@ -486,13 +511,23 @@ static void cleanup()
static int create_pipe(int filedes[], int flags)
{
int ret;
int ret = -1;
#ifdef HAVE_PIPE2
/* use pipe2(2) whenever possible, since it can thread-safely create a
* cloexec pair of pipes. Without it, we have a race condition setting
* FD_CLOEXEC
*/
ret = pipe2(filedes, O_CLOEXEC);
# ifdef O_NOSIGPIPE
/* try first with O_NOSIGPIPE */
ret = pipe2(filedes, O_CLOEXEC | O_NOSIGPIPE);
if (ret == -1) {
/* O_NOSIGPIPE not supported, ignore SIGPIPE */
ignore_sigpipe();
}
# endif
if (ret == -1)
ret = pipe2(filedes, O_CLOEXEC);
if (ret == -1)
return ret;