diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-01-31 19:26:12 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-01-31 19:26:12 +0000 |
commit | 9ec0ecbfdde2396c4c1c91b4a040ccb006f424c2 (patch) | |
tree | 1a5d4a1c3f542afe6ed737f297c1a77e822e593f /init | |
parent | 4ae8a05b131836184eb32c440a6bf814ff81b069 (diff) | |
download | busybox-w32-9ec0ecbfdde2396c4c1c91b4a040ccb006f424c2.tar.gz busybox-w32-9ec0ecbfdde2396c4c1c91b4a040ccb006f424c2.tar.bz2 busybox-w32-9ec0ecbfdde2396c4c1c91b4a040ccb006f424c2.zip |
init: remove wait() loop on restart, it may be dangerous
Diffstat (limited to 'init')
-rw-r--r-- | init/init.c | 37 |
1 files changed, 22 insertions, 15 deletions
diff --git a/init/init.c b/init/init.c index 7ba8b67ec..68e624294 100644 --- a/init/init.c +++ b/init/init.c | |||
@@ -418,14 +418,16 @@ static pid_t run(const struct init_action *a) | |||
418 | _exit(-1); | 418 | _exit(-1); |
419 | } | 419 | } |
420 | 420 | ||
421 | static struct init_action *mark_terminated(int pid) | 421 | static struct init_action *mark_terminated(pid_t pid) |
422 | { | 422 | { |
423 | struct init_action *a; | 423 | struct init_action *a; |
424 | 424 | ||
425 | for (a = init_action_list; a; a = a->next) { | 425 | if (pid > 0) { |
426 | if (a->pid == pid) { | 426 | for (a = init_action_list; a; a = a->next) { |
427 | a->pid = 0; | 427 | if (a->pid == pid) { |
428 | return a; | 428 | a->pid = 0; |
429 | return a; | ||
430 | } | ||
429 | } | 431 | } |
430 | } | 432 | } |
431 | return NULL; | 433 | return NULL; |
@@ -444,7 +446,7 @@ static void waitfor(pid_t pid) | |||
444 | mark_terminated(wpid); | 446 | mark_terminated(wpid); |
445 | /* Unsafe. SIGTSTP handler might have wait'ed it already */ | 447 | /* Unsafe. SIGTSTP handler might have wait'ed it already */ |
446 | /*if (wpid == pid) break;*/ | 448 | /*if (wpid == pid) break;*/ |
447 | /* More reliable */ | 449 | /* More reliable: */ |
448 | if (kill(pid, 0)) | 450 | if (kill(pid, 0)) |
449 | break; | 451 | break; |
450 | } | 452 | } |
@@ -697,11 +699,11 @@ static void halt_reboot_pwoff(int sig) | |||
697 | */ | 699 | */ |
698 | static void stop_handler(int sig UNUSED_PARAM) | 700 | static void stop_handler(int sig UNUSED_PARAM) |
699 | { | 701 | { |
700 | int saved_errno; | ||
701 | smallint saved_bb_got_signal; | 702 | smallint saved_bb_got_signal; |
703 | int saved_errno; | ||
702 | 704 | ||
703 | saved_errno = errno; | ||
704 | saved_bb_got_signal = bb_got_signal; | 705 | saved_bb_got_signal = bb_got_signal; |
706 | saved_errno = errno; | ||
705 | signal(SIGCONT, record_signo); | 707 | signal(SIGCONT, record_signo); |
706 | 708 | ||
707 | while (1) { | 709 | while (1) { |
@@ -714,14 +716,13 @@ static void stop_handler(int sig UNUSED_PARAM) | |||
714 | * code which is resilient against this. | 716 | * code which is resilient against this. |
715 | */ | 717 | */ |
716 | wpid = wait_any_nohang(NULL); | 718 | wpid = wait_any_nohang(NULL); |
717 | if (wpid > 0) | 719 | mark_terminated(wpid); |
718 | mark_terminated(wpid); | ||
719 | sleep(1); | 720 | sleep(1); |
720 | } | 721 | } |
721 | 722 | ||
722 | signal(SIGCONT, SIG_DFL); | 723 | signal(SIGCONT, SIG_DFL); |
723 | bb_got_signal = saved_bb_got_signal; | ||
724 | errno = saved_errno; | 724 | errno = saved_errno; |
725 | bb_got_signal = saved_bb_got_signal; | ||
725 | } | 726 | } |
726 | 727 | ||
727 | /* Handler for QUIT - exec "restart" action, | 728 | /* Handler for QUIT - exec "restart" action, |
@@ -747,8 +748,14 @@ static void restart_handler(int sig UNUSED_PARAM) | |||
747 | 748 | ||
748 | if (open_stdio_to_tty(a->terminal)) { | 749 | if (open_stdio_to_tty(a->terminal)) { |
749 | dbg_message(L_CONSOLE, "Trying to re-exec %s", a->command); | 750 | dbg_message(L_CONSOLE, "Trying to re-exec %s", a->command); |
750 | while (wait(NULL) > 0) | 751 | /* Theoretically should be safe. |
751 | continue; | 752 | * But in practice, kernel bugs may leave |
753 | * unkillable processes, and wait() may block forever. | ||
754 | * Oh well. Hoping "new" init won't be too surprised | ||
755 | * by having children it didn't create. | ||
756 | */ | ||
757 | //while (wait(NULL) > 0) | ||
758 | // continue; | ||
752 | init_exec(a->command); | 759 | init_exec(a->command); |
753 | } | 760 | } |
754 | /* Open or exec failed */ | 761 | /* Open or exec failed */ |
@@ -990,14 +997,14 @@ int init_main(int argc UNUSED_PARAM, char **argv) | |||
990 | 997 | ||
991 | got_sigs |= check_delayed_sigs(); | 998 | got_sigs |= check_delayed_sigs(); |
992 | 999 | ||
1000 | if (got_sigs) | ||
1001 | goto dont_block; | ||
993 | /* Wait for any child process to exit. | 1002 | /* Wait for any child process to exit. |
994 | * NB: "delayed" signals will also interrupt this wait(), | 1003 | * NB: "delayed" signals will also interrupt this wait(), |
995 | * bb_signals_recursive_norestart() set them up for that. | 1004 | * bb_signals_recursive_norestart() set them up for that. |
996 | * This guarantees we won't be stuck here | 1005 | * This guarantees we won't be stuck here |
997 | * till next orphan dies. | 1006 | * till next orphan dies. |
998 | */ | 1007 | */ |
999 | if (got_sigs) | ||
1000 | goto dont_block; | ||
1001 | wpid = wait(NULL); | 1008 | wpid = wait(NULL); |
1002 | while (wpid > 0) { | 1009 | while (wpid > 0) { |
1003 | struct init_action *a = mark_terminated(wpid); | 1010 | struct init_action *a = mark_terminated(wpid); |