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 | |
| 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
| -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); |
