aboutsummaryrefslogtreecommitdiff
path: root/init
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-03-10 16:01:57 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-03-10 16:01:57 +0000
commit4774179cb9e04030485773adf2b7b1055a10faeb (patch)
tree91bb5c51f9f4e3036298d7bb5490621b3e7a3ee6 /init
parent245f91b6494063c5fa1f3f586771e2ac100a69a9 (diff)
downloadbusybox-w32-4774179cb9e04030485773adf2b7b1055a10faeb.tar.gz
busybox-w32-4774179cb9e04030485773adf2b7b1055a10faeb.tar.bz2
busybox-w32-4774179cb9e04030485773adf2b7b1055a10faeb.zip
mail.c: more robust handling of SIGCHLD
init: more robust signal handling
Diffstat (limited to 'init')
-rw-r--r--init/init.c41
1 files changed, 23 insertions, 18 deletions
diff --git a/init/init.c b/init/init.c
index 5b9820b4a..5c344cb63 100644
--- a/init/init.c
+++ b/init/init.c
@@ -336,20 +336,22 @@ static pid_t run(const struct init_action *a)
336{ 336{
337 pid_t pid; 337 pid_t pid;
338 338
339 /* Careful: don't be affected by a signal in vforked child */
340 sigprocmask_allsigs(SIG_BLOCK);
339 if (BB_MMU && (a->action_type & ASKFIRST)) 341 if (BB_MMU && (a->action_type & ASKFIRST))
340 pid = fork(); 342 pid = fork();
341 else 343 else
342 pid = vfork(); 344 pid = vfork();
343 if (pid < 0) 345 if (pid < 0)
344 message(L_LOG | L_CONSOLE, "can't fork"); 346 message(L_LOG | L_CONSOLE, "can't fork");
345 if (pid) 347 if (pid) {
348 sigprocmask_allsigs(SIG_UNBLOCK);
346 return pid; /* Parent or error */ 349 return pid; /* Parent or error */
350 }
347 351
348 /* Child */ 352 /* Child */
349 353
350 /* Reset signal handlers that were set by the parent process */ 354 /* Reset signal handlers that were set by the parent process */
351//TODO: block signals across fork(), prevent them to affect child before
352//signals are reset?
353 bb_signals(0 355 bb_signals(0
354 + (1 << SIGUSR1) 356 + (1 << SIGUSR1)
355 + (1 << SIGUSR2) 357 + (1 << SIGUSR2)
@@ -359,6 +361,7 @@ static pid_t run(const struct init_action *a)
359 + (1 << SIGHUP) 361 + (1 << SIGHUP)
360 + (1 << SIGTSTP) 362 + (1 << SIGTSTP)
361 , SIG_DFL); 363 , SIG_DFL);
364 sigprocmask_allsigs(SIG_UNBLOCK);
362 365
363 /* Create a new session and make ourself the process group leader */ 366 /* Create a new session and make ourself the process group leader */
364 setsid(); 367 setsid();
@@ -982,40 +985,42 @@ int init_main(int argc UNUSED_PARAM, char **argv)
982 * NB: if delayed signal happened, avoid blocking in wait(). 985 * NB: if delayed signal happened, avoid blocking in wait().
983 */ 986 */
984 while (1) { 987 while (1) {
985 pid_t wpid; 988 int maybe_WNOHANG;
986 int got_sigs;
987 989
988 got_sigs = check_delayed_sigs(); 990 maybe_WNOHANG = check_delayed_sigs();
989 991
990 /* (Re)run the respawn/askfirst stuff */ 992 /* (Re)run the respawn/askfirst stuff */
991 run_actions(RESPAWN | ASKFIRST); 993 run_actions(RESPAWN | ASKFIRST);
992 994 maybe_WNOHANG |= check_delayed_sigs();
993 got_sigs |= check_delayed_sigs();
994 995
995 /* Don't consume all CPU time - sleep a bit */ 996 /* Don't consume all CPU time - sleep a bit */
996 sleep(1); 997 sleep(1);
998 maybe_WNOHANG |= check_delayed_sigs();
997 999
998 got_sigs |= check_delayed_sigs(); 1000 /* Wait for any child process(es) to exit.
999
1000 if (got_sigs)
1001 goto dont_block;
1002 /* Wait for any child process to exit.
1003 * NB: "delayed" signals will also interrupt this wait(), 1001 * NB: "delayed" signals will also interrupt this wait(),
1004 * bb_signals_recursive_norestart() set them up for that. 1002 * bb_signals_recursive_norestart() set them up for that.
1005 * This guarantees we won't be stuck here 1003 * This guarantees we won't be stuck here
1006 * till next orphan dies. 1004 * till next orphan dies.
1007 */ 1005 */
1008 wpid = wait(NULL); 1006 if (maybe_WNOHANG)
1009 while (wpid > 0) { 1007 maybe_WNOHANG = WNOHANG;
1010 struct init_action *a = mark_terminated(wpid); 1008 while (1) {
1009 pid_t wpid;
1010 struct init_action *a;
1011
1012 wpid = waitpid(-1, NULL, maybe_WNOHANG);
1013 if (wpid <= 0)
1014 break;
1015
1016 a = mark_terminated(wpid);
1011 if (a) { 1017 if (a) {
1012 message(L_LOG, "process '%s' (pid %d) exited. " 1018 message(L_LOG, "process '%s' (pid %d) exited. "
1013 "Scheduling for restart.", 1019 "Scheduling for restart.",
1014 a->command, wpid); 1020 a->command, wpid);
1015 } 1021 }
1016 /* See if anyone else is waiting to be reaped */ 1022 /* See if anyone else is waiting to be reaped */
1017 dont_block: 1023 maybe_WNOHANG = WNOHANG;
1018 wpid = wait_any_nohang(NULL);
1019 } 1024 }
1020 } /* while (1) */ 1025 } /* while (1) */
1021} 1026}