svn commit: [25597] trunk/busybox: init mailutils

vda at busybox.net vda at busybox.net
Tue Mar 10 16:01:58 UTC 2009


Author: vda
Date: 2009-03-10 16:01:57 +0000 (Tue, 10 Mar 2009)
New Revision: 25597

Log:
mail.c: more robust handling of SIGCHLD
init: more robust signal handling



Modified:
   trunk/busybox/init/init.c
   trunk/busybox/mailutils/mail.c


Changeset:
Modified: trunk/busybox/init/init.c
===================================================================
--- trunk/busybox/init/init.c	2009-03-10 14:43:22 UTC (rev 25596)
+++ trunk/busybox/init/init.c	2009-03-10 16:01:57 UTC (rev 25597)
@@ -336,20 +336,22 @@
 {
 	pid_t pid;
 
+	/* Careful: don't be affected by a signal in vforked child */
+	sigprocmask_allsigs(SIG_BLOCK);
 	if (BB_MMU && (a->action_type & ASKFIRST))
 		pid = fork();
 	else
 		pid = vfork();
 	if (pid < 0)
 		message(L_LOG | L_CONSOLE, "can't fork");
-	if (pid)
+	if (pid) {
+		sigprocmask_allsigs(SIG_UNBLOCK);
 		return pid; /* Parent or error */
+	}
 
 	/* Child */
 
 	/* Reset signal handlers that were set by the parent process */
-//TODO: block signals across fork(), prevent them to affect child before
-//signals are reset?
 	bb_signals(0
 		+ (1 << SIGUSR1)
 		+ (1 << SIGUSR2)
@@ -359,6 +361,7 @@
 		+ (1 << SIGHUP)
 		+ (1 << SIGTSTP)
 		, SIG_DFL);
+	sigprocmask_allsigs(SIG_UNBLOCK);
 
 	/* Create a new session and make ourself the process group leader */
 	setsid();
@@ -982,40 +985,42 @@
 	 * NB: if delayed signal happened, avoid blocking in wait().
 	 */
 	while (1) {
-		pid_t wpid;
-		int got_sigs;
+		int maybe_WNOHANG;
 
-		got_sigs = check_delayed_sigs();
+		maybe_WNOHANG = check_delayed_sigs();
 
 		/* (Re)run the respawn/askfirst stuff */
 		run_actions(RESPAWN | ASKFIRST);
+		maybe_WNOHANG |= check_delayed_sigs();
 
-		got_sigs |= check_delayed_sigs();
-
 		/* Don't consume all CPU time - sleep a bit */
 		sleep(1);
+		maybe_WNOHANG |= check_delayed_sigs();
 
-		got_sigs |= check_delayed_sigs();
-
-		if (got_sigs)
-			goto dont_block;
-		/* Wait for any child process to exit.
+		/* Wait for any child process(es) to exit.
 		 * NB: "delayed" signals will also interrupt this wait(),
 		 * bb_signals_recursive_norestart() set them up for that.
 		 * This guarantees we won't be stuck here
 		 * till next orphan dies.
 		 */
-		wpid = wait(NULL);
-		while (wpid > 0) {
-			struct init_action *a = mark_terminated(wpid);
+		if (maybe_WNOHANG)
+			maybe_WNOHANG = WNOHANG;
+		while (1) {
+			pid_t wpid;
+			struct init_action *a;
+
+			wpid = waitpid(-1, NULL, maybe_WNOHANG);
+			if (wpid <= 0)
+				break;
+
+			a = mark_terminated(wpid);
 			if (a) {
 				message(L_LOG, "process '%s' (pid %d) exited. "
 						"Scheduling for restart.",
 						a->command, wpid);
 			}
 			/* See if anyone else is waiting to be reaped */
- dont_block:
-			wpid = wait_any_nohang(NULL);
+			maybe_WNOHANG = WNOHANG;
 		}
 	} /* while (1) */
 }

Modified: trunk/busybox/mailutils/mail.c
===================================================================
--- trunk/busybox/mailutils/mail.c	2009-03-10 14:43:22 UTC (rev 25596)
+++ trunk/busybox/mailutils/mail.c	2009-03-10 16:01:57 UTC (rev 25597)
@@ -48,6 +48,12 @@
 	xpipe(pipes);
 	xpipe(pipes + 2);
 
+	// NB: handler must be installed before vfork
+	bb_signals(0
+		+ (1 << SIGCHLD)
+		+ (1 << SIGALRM)
+		, signal_handler);
+
 	G.helper_pid = vfork();
 	if (G.helper_pid < 0)
 		bb_perror_msg_and_die("vfork");
@@ -60,15 +66,12 @@
 
 	if (!G.helper_pid) {
 		// child: try to execute connection helper
+		// NB: SIGCHLD & SIGALRM revert to SIG_DFL on exec
 		BB_EXECVP(*argv, (char **)argv);
 		_exit(127);
 	}
 
 	// parent
-	bb_signals(0
-		+ (1 << SIGCHLD)
-		+ (1 << SIGALRM)
-		, signal_handler);
 	// check whether child is alive
 	//redundant:signal_handler(SIGCHLD);
 	// child seems OK -> parent goes on



More information about the busybox-cvs mailing list