aboutsummaryrefslogtreecommitdiff
path: root/init/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'init/init.c')
-rw-r--r--init/init.c68
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
972static
973void 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
957int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 998int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
958int init_main(int argc UNUSED_PARAM, char **argv) 999int 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