If init dies, log a signal which killed it, if any.
PATCH 1/1 If init dies, log a signal which killed it, if any.
I just received another user's pleas for help when their init mystriously dies. I again explained that they need to check whether it dies because of bad instruction, a segv, or something else.
Which prompted me to make kernel do this first step automatically. We can easily detect when the death is from e.g. SIGILL, and let user know that.
The code is fairly self-explanatory. Compile-tested.
--- kernel/exit.c | 23 ++++++++++++++++++++++- 1 files changed, 22 insertions(+), 1 deletions(-)
kernel/exit.c +22 -1
@@ -710,8 +710,29 @@ static struct task_struct *find_new_reaper(struct task_struct *father)if (unlikely (pid_ns->child_reaper == father)) {write_unlock_irq (&tasklist_lock); -if (unlikely (pid_ns == &init_pid_ns)) +if (unlikely (pid_ns == &init_pid_ns)) { +/* +* The situation when init segfaults is rather typical. +* Give some useful diagnostics: do we die on signal? +*/ +if (fatal_signal_pending (father)) { +const char *msg ="" ; +sigset_t *mask = &father->pending.signal; +/* Only force_sig()ned signals kill init */ +if (sigismember (mask,SIGSEGV )) + msg =" SIGSEGV" ; +if (sigismember (mask,SIGBUS )) + msg =" SIGBUS" ; +if (sigismember (mask,SIGILL )) + msg =" SIGILL" ; +if (sigismember (mask,SIGFPE )) + msg =" SIGFPE" ; +/* (do we want to check SIGTRAP too?) */ +printk (KERN_ERR +"init received fatal signal%s\n" , msg); + }panic ("Attempted to kill init!" ); + }zap_pid_ns_processes (pid_ns);write_lock_irq (&tasklist_lock);
Signature · 1 line
1.7.7.5
Quoted 21 lines · Denys Vlasenko
I just received another user's pleas for help when their init mystriously dies. I again explained that they need to check whether it dies because of bad instruction, a segv, or something else.
Which prompted me to make kernel do this first step automatically. We can easily detect when the death is from e.g. SIGILL, and let user know that.
The code is fairly self-explanatory. Compile-tested.
Signed-off-by Denys Vlasenko <[email protected]>--- kernel/exit.c | 23 ++++++++++++++++++++++- 1 files changed, 22 insertions(+), 1 deletions(-)kernel/exit.c +0
-0
kernel/exit.c static struct task_struct *find_new_reaper(struct task_struct *father) · line 718
Quoted 10 lines
kernel/exit.c +6
-1@@ -710,8 +710,29 @@ static struct task_struct *find_new_reaper(struct task_struct *father)if (unlikely (pid_ns->child_reaper == father)) {write_unlock_irq (&tasklist_lock); -if (unlikely (pid_ns == &init_pid_ns)) +if (unlikely (pid_ns == &init_pid_ns)) { +/* +* The situation when init segfaults is rather typical. +* Give some useful diagnostics: do we die on signal? +*/ +if (fatal_signal_pending (father)) {
The fatal signal can be already dequeued. Although mostly this works.
kernel/exit.c static struct task_struct *find_new_reaper(struct task_struct *father) · line 729
Quoted 11 lines
kernel/exit.c +11
-0+const char *msg ="" ; +sigset_t *mask = &father->pending.signal; +/* Only force_sig()ned signals kill init */ +if (sigismember (mask,SIGSEGV )) + msg =" SIGSEGV" ; +if (sigismember (mask,SIGBUS )) + msg =" SIGBUS" ; +if (sigismember (mask,SIGILL )) + msg =" SIGILL" ; +if (sigismember (mask,SIGFPE )) + msg =" SIGFPE" ;
This doesn't look right too. Again, if it was killed by SIGSEGV this signal can be dequeued and not pending.
kernel/exit.c static struct task_struct *find_new_reaper(struct task_struct *father) · line 733
Quoted 4 lines
kernel/exit.c +4
-0+/* (do we want to check SIGTRAP too?) */ +printk (KERN_ERR +"init received fatal signal%s\n" , msg); + }
I'd suggest this trivial change instead,
- panic("Attempted to kill init!");
+ panic("Attempted to kill init! code=%08x\n",
+ father->signal->group_exit_code ?: father->exit_code);Oleg.