[PATCH] libc: make system() block SIGCHLD

Richard Braun rbraun at sceen.net
Sun Jan 15 11:46:33 UTC 2012


When built without NPTL support (or for a sparc target), the system()
function doesn't conform to its specification. Namely, it resets the
SIGCHLD handler to its default instead of blocking the signal, which
may result in "lost" signals if a custom handler was installed.
Replace this by appropriate calls to sigprocmask().

Signed-off-by: Richard Braun <rbraun at sceen.net>
---
 libc/stdlib/system.c |   18 ++++++++++--------
 1 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/libc/stdlib/system.c b/libc/stdlib/system.c
index a0ff726..99000d2 100644
--- a/libc/stdlib/system.c
+++ b/libc/stdlib/system.c
@@ -33,25 +33,26 @@ extern __typeof(system) __libc_system;
 int __libc_system(const char *command)
 {
 	int wait_val, pid;
-	__sighandler_t save_quit, save_int, save_chld;
+	__sighandler_t save_quit, save_int;
+	sigset_t smask, omask;
 
 	if (command == 0)
 		return 1;
 
 	save_quit = signal(SIGQUIT, SIG_IGN);
 	save_int = signal(SIGINT, SIG_IGN);
-	save_chld = signal(SIGCHLD, SIG_DFL);
+	sigemptyset(&smask);
+	sigaddset(&smask, SIGCHLD);
+	sigprocmask(SIG_BLOCK, &smask, &omask);
 
 	if ((pid = vfork()) < 0) {
-		signal(SIGQUIT, save_quit);
-		signal(SIGINT, save_int);
-		signal(SIGCHLD, save_chld);
-		return -1;
+		wait_val = -1;
+		goto out;
 	}
 	if (pid == 0) {
 		signal(SIGQUIT, SIG_DFL);
 		signal(SIGINT, SIG_DFL);
-		signal(SIGCHLD, SIG_DFL);
+		sigprocmask(SIG_SETMASK, &omask, NULL);
 
 		execl("/bin/sh", "sh", "-c", command, (char *) 0);
 		_exit(127);
@@ -67,9 +68,10 @@ int __libc_system(const char *command)
 	if (wait4(pid, &wait_val, 0, 0) == -1)
 		wait_val = -1;
 
+out:
 	signal(SIGQUIT, save_quit);
 	signal(SIGINT, save_int);
-	signal(SIGCHLD, save_chld);
+	sigprocmask(SIG_SETMASK, &omask, NULL);
 	return wait_val;
 }
 #else
-- 
1.7.2.5



More information about the uClibc mailing list