diff options
Diffstat (limited to 'init/init.c')
-rw-r--r-- | init/init.c | 68 |
1 files changed, 61 insertions, 7 deletions
diff --git a/init/init.c b/init/init.c index 645f694c0..724894698 100644 --- a/init/init.c +++ b/init/init.c | |||
@@ -108,6 +108,8 @@ | |||
108 | //config: Note that on Linux, init attempts to detect serial terminal and | 108 | //config: Note that on Linux, init attempts to detect serial terminal and |
109 | //config: sets TERM to "vt102" if one is found. | 109 | //config: sets TERM to "vt102" if one is found. |
110 | 110 | ||
111 | #define DEBUG_SEGV_HANDLER 0 | ||
112 | |||
111 | #include "libbb.h" | 113 | #include "libbb.h" |
112 | #include <syslog.h> | 114 | #include <syslog.h> |
113 | #include <paths.h> | 115 | #include <paths.h> |
@@ -118,6 +120,15 @@ | |||
118 | #endif | 120 | #endif |
119 | #include "reboot.h" /* reboot() constants */ | 121 | #include "reboot.h" /* reboot() constants */ |
120 | 122 | ||
123 | #if DEBUG_SEGV_HANDLER | ||
124 | # undef _GNU_SOURCE | ||
125 | # define _GNU_SOURCE 1 | ||
126 | # undef __USE_GNU | ||
127 | # define __USE_GNU 1 | ||
128 | # include <execinfo.h> | ||
129 | # include <sys/ucontext.h> | ||
130 | #endif | ||
131 | |||
121 | /* Used only for sanitizing purposes in set_sane_term() below. On systems where | 132 | /* Used only for sanitizing purposes in set_sane_term() below. On systems where |
122 | * the baud rate is stored in a separate field, we can safely disable them. */ | 133 | * the baud rate is stored in a separate field, we can safely disable them. */ |
123 | #ifndef CBAUD | 134 | #ifndef CBAUD |
@@ -523,15 +534,17 @@ static struct init_action *mark_terminated(pid_t pid) | |||
523 | struct init_action *a; | 534 | struct init_action *a; |
524 | 535 | ||
525 | if (pid > 0) { | 536 | if (pid > 0) { |
537 | update_utmp(pid, DEAD_PROCESS, | ||
538 | /*tty_name:*/ NULL, | ||
539 | /*username:*/ NULL, | ||
540 | /*hostname:*/ NULL | ||
541 | ); | ||
526 | for (a = init_action_list; a; a = a->next) { | 542 | for (a = init_action_list; a; a = a->next) { |
527 | if (a->pid == pid) { | 543 | if (a->pid == pid) { |
528 | a->pid = 0; | 544 | a->pid = 0; |
529 | return a; | 545 | return a; |
530 | } | 546 | } |
531 | } | 547 | } |
532 | update_utmp(pid, DEAD_PROCESS, /*tty_name:*/ NULL, | ||
533 | /*username:*/ NULL, | ||
534 | /*hostname:*/ NULL); | ||
535 | } | 548 | } |
536 | return NULL; | 549 | return NULL; |
537 | } | 550 | } |
@@ -596,7 +609,7 @@ static void new_init_action(uint8_t action_type, const char *command, const char | |||
596 | */ | 609 | */ |
597 | nextp = &init_action_list; | 610 | nextp = &init_action_list; |
598 | while ((a = *nextp) != NULL) { | 611 | while ((a = *nextp) != NULL) { |
599 | /* Don't enter action if it's already in the list, | 612 | /* Don't enter action if it's already in the list. |
600 | * This prevents losing running RESPAWNs. | 613 | * This prevents losing running RESPAWNs. |
601 | */ | 614 | */ |
602 | if (strcmp(a->command, command) == 0 | 615 | if (strcmp(a->command, command) == 0 |
@@ -608,14 +621,15 @@ static void new_init_action(uint8_t action_type, const char *command, const char | |||
608 | while (*nextp != NULL) | 621 | while (*nextp != NULL) |
609 | nextp = &(*nextp)->next; | 622 | nextp = &(*nextp)->next; |
610 | a->next = NULL; | 623 | a->next = NULL; |
611 | break; | 624 | goto append; |
612 | } | 625 | } |
613 | nextp = &a->next; | 626 | nextp = &a->next; |
614 | } | 627 | } |
615 | 628 | ||
616 | if (!a) | 629 | a = xzalloc(sizeof(*a)); |
617 | a = xzalloc(sizeof(*a)); | 630 | |
618 | /* Append to the end of the list */ | 631 | /* Append to the end of the list */ |
632 | append: | ||
619 | *nextp = a; | 633 | *nextp = a; |
620 | a->action_type = action_type; | 634 | a->action_type = action_type; |
621 | safe_strncpy(a->command, command, sizeof(a->command)); | 635 | safe_strncpy(a->command, command, sizeof(a->command)); |
@@ -954,6 +968,33 @@ static int check_delayed_sigs(void) | |||
954 | } | 968 | } |
955 | } | 969 | } |
956 | 970 | ||
971 | #if DEBUG_SEGV_HANDLER | ||
972 | static | ||
973 | void handle_sigsegv(int sig, siginfo_t *info, void *ucontext) | ||
974 | { | ||
975 | long ip; | ||
976 | ucontext_t *uc; | ||
977 | |||
978 | uc = ucontext; | ||
979 | ip = uc->uc_mcontext.gregs[REG_EIP]; | ||
980 | fdprintf(2, "signal:%d address:0x%lx ip:0x%lx\n", | ||
981 | sig, | ||
982 | /* this is void*, but using %p would print "(null)" | ||
983 | * even for ptrs which are not exactly 0, but, say, 0x123: | ||
984 | */ | ||
985 | (long)info->si_addr, | ||
986 | ip); | ||
987 | { | ||
988 | /* glibc extension */ | ||
989 | void *array[50]; | ||
990 | int size; | ||
991 | size = backtrace(array, 50); | ||
992 | backtrace_symbols_fd(array, size, 2); | ||
993 | } | ||
994 | for (;;) sleep(9999); | ||
995 | } | ||
996 | #endif | ||
997 | |||
957 | int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 998 | int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
958 | int init_main(int argc UNUSED_PARAM, char **argv) | 999 | int init_main(int argc UNUSED_PARAM, char **argv) |
959 | { | 1000 | { |
@@ -961,6 +1002,19 @@ int init_main(int argc UNUSED_PARAM, char **argv) | |||
961 | return kill(1, SIGHUP); | 1002 | return kill(1, SIGHUP); |
962 | } | 1003 | } |
963 | 1004 | ||
1005 | #if DEBUG_SEGV_HANDLER | ||
1006 | { | ||
1007 | struct sigaction sa; | ||
1008 | memset(&sa, 0, sizeof(sa)); | ||
1009 | sa.sa_sigaction = handle_sigsegv; | ||
1010 | sa.sa_flags = SA_SIGINFO; | ||
1011 | sigaction(SIGSEGV, &sa, NULL); | ||
1012 | sigaction(SIGILL, &sa, NULL); | ||
1013 | sigaction(SIGFPE, &sa, NULL); | ||
1014 | sigaction(SIGBUS, &sa, NULL); | ||
1015 | } | ||
1016 | #endif | ||
1017 | |||
964 | if (!DEBUG_INIT) { | 1018 | if (!DEBUG_INIT) { |
965 | /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */ | 1019 | /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */ |
966 | if (getpid() != 1 | 1020 | if (getpid() != 1 |