NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/57527: system() waits for last child if SIG_CHLD is ignored
The following reply was made to PR kern/57527; it has been noted by GNATS.
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
To: dholland%NetBSD.org@localhost
Cc: gnats-bugs%NetBSD.org@localhost
Subject: Re: kern/57527: system() waits for last child if SIG_CHLD is ignored
Date: Sat, 15 Jul 2023 21:48:47 +0000
This is a multi-part message in MIME format.
--=_cMRXY1mpK2XMc2pQZgnqCub6ZuhP0lAV
> Date: Sat, 15 Jul 2023 20:46:43 +0000
> From: David Holland <dholland-bugs%netbsd.org@localhost>
>
> On Sat, Jul 15, 2023 at 08:05:02PM +0000, Taylor R Campbell wrote:
> > However, it doesn't seem to address the possibility of changing
> > SIGCHLD to SIG_DFL if and only if it was already set to SIG_IGN, if
> > I'm reading it correctly. So maybe the attached patch will resolve
> > the issue in system(3)?
>
> It's worse than that; you could race with another thread setting
> SIG_IGN.
>
> Maybe that gets into "don't do that" territory though.
Yes, it's in `don't do that' territory. POSIX says:
Using the system() function in more than one thread in a process or
when the SIGCHLD signal is being manipulated by more than one
thread in a process may produce unexpected results.
https://pubs.opengroup.org/onlinepubs/9699919799/functions/system.html
--=_cMRXY1mpK2XMc2pQZgnqCub6ZuhP0lAV
Content-Type: text/plain; charset="ISO-8859-1"; name="pr57527-system"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="pr57527-system.patch"
From 51954a3b812c57c57835be1b4b06c5c9918c5783 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Sat, 15 Jul 2023 20:02:28 +0000
Subject: [PATCH] system(3): Change SIG_IGN to SIG_DFL for SIGCHLD while we
work.
PR kern/57527
---
lib/libc/stdlib/system.c | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/lib/libc/stdlib/system.c b/lib/libc/stdlib/system.c
index 5a19bc9e0568..4d3e45f1892a 100644
--- a/lib/libc/stdlib/system.c
+++ b/lib/libc/stdlib/system.c
@@ -54,7 +54,7 @@ int
system(const char *command)
{
pid_t pid;
- struct sigaction intsa, quitsa, sa;
+ struct sigaction chldsa, intsa, quitsa, sa;
sigset_t nmask, omask, sigdefault;
int pstat;
const char *argp[] =3D {"sh", "-c", "--", command, NULL};
@@ -90,6 +90,32 @@ system(const char *command)
return -1;
}
=20
+ /*
+ * Make sure SIGCHLD is not set to SIG_IGN, because that means
+ * waitpid will wait until _all_ children have exited, under a
+ * peculiar clause of POSIX enshrining a quirk of SysV
+ * semantics.
+ *
+ * If SIGCHLD was set to anything other than SIG_IGN, we must
+ * not interfere with it -- changing the action may clear any
+ * queued signals for for processes _other_ than the one that
+ * system(3) itself spawns.
+ */
+ if (sigaction(SIGCHLD, NULL, &chldsa) =3D=3D -1) {
+ (void)sigprocmask(SIG_SETMASK, &omask, NULL);
+ sigaction(SIGINT, &intsa, NULL);
+ sigaction(SIGQUIT, &quitsa, NULL);
+ return -1;
+ }
+ if (chldsa.sa_handler =3D=3D SIG_IGN &&
+ sigaction(SIGCHLD, &(struct sigaction){ .sa_handler =3D SIG_DFL },
+ NULL) =3D=3D -1) {
+ (void)sigprocmask(SIG_SETMASK, &omask, NULL);
+ sigaction(SIGINT, &intsa, NULL);
+ sigaction(SIGQUIT, &quitsa, NULL);
+ return -1;
+ }
+
/*
* We arrange to inherit all signal handlers from the caller by
* default, except possibly SIGINT and SIGQUIT. These we have
@@ -133,7 +159,9 @@ system(const char *command)
}
}
=20
-out: sigaction(SIGINT, &intsa, NULL);
+out: if (chldsa.sa_handler =3D=3D SIG_IGN)
+ sigaction(SIGCHLD, &chldsa, NULL);
+ sigaction(SIGINT, &intsa, NULL);
sigaction(SIGQUIT, &quitsa, NULL);
(void)sigprocmask(SIG_SETMASK, &omask, NULL);
=20
--=_cMRXY1mpK2XMc2pQZgnqCub6ZuhP0lAV--
Home |
Main Index |
Thread Index |
Old Index