X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=kernel%2Fexit.c;h=5b0fb9f09f212d05642dd343be2692a2b0a039b7;hb=9d8f53f2bba3c2c06e1e78126222aecf91f8ecdd;hp=93851bcd9584597daac893eee17559c02d8b4a96;hpb=c06fec5022ebe014af876da2df4a0eee836e97c8;p=linux-2.6 diff --git a/kernel/exit.c b/kernel/exit.c index 93851bcd95..5b0fb9f09f 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,8 @@ extern struct task_struct *child_reaper; int getrusage(struct task_struct *, int, struct rusage __user *); +static void exit_mm(struct task_struct * tsk); + static void __unhash_process(struct task_struct *p) { nr_threads--; @@ -69,6 +72,11 @@ repeat: BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children)); __exit_signal(p); __exit_sighand(p); + /* + * Note that the fastpath in sys_times depends on __exit_signal having + * updated the counters before a task is removed from the tasklist of + * the process by __unhash_process. + */ __unhash_process(p); /* @@ -209,7 +217,7 @@ static inline int has_stopped_jobs(int pgrp) } /** - * reparent_to_init() - Reparent the calling kernel thread to the init task. + * reparent_to_init - Reparent the calling kernel thread to the init task. * * If a kernel thread is launched as a result of a system call, or if * it ever exits, it should generally reparent itself to init so that @@ -277,7 +285,7 @@ void set_special_pids(pid_t session, pid_t pgrp) */ int allow_signal(int sig) { - if (sig < 1 || sig > _NSIG) + if (!valid_signal(sig) || sig < 1) return -EINVAL; spin_lock_irq(¤t->sighand->siglock); @@ -298,7 +306,7 @@ EXPORT_SYMBOL(allow_signal); int disallow_signal(int sig) { - if (sig < 1 || sig > _NSIG) + if (!valid_signal(sig) || sig < 1) return -EINVAL; spin_lock_irq(¤t->sighand->siglock); @@ -473,7 +481,7 @@ EXPORT_SYMBOL_GPL(exit_fs); * Turn us into a lazy TLB process if we * aren't already.. */ -void exit_mm(struct task_struct * tsk) +static void exit_mm(struct task_struct * tsk) { struct mm_struct *mm = tsk->mm; @@ -776,6 +784,8 @@ fastcall NORET_TYPE void do_exit(long code) profile_task_exit(tsk); + WARN_ON(atomic_read(&tsk->fs_excl)); + if (unlikely(in_interrupt())) panic("Aiee, killing interrupt handler!"); if (unlikely(!tsk->pid)) @@ -790,6 +800,17 @@ fastcall NORET_TYPE void do_exit(long code) ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP); } + /* + * We're taking recursive faults here in do_exit. Safest is to just + * leave this task alone and wait for reboot. + */ + if (unlikely(tsk->flags & PF_EXITING)) { + printk(KERN_ALERT + "Fixing recursive fault but reboot is needed!\n"); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + } + tsk->flags |= PF_EXITING; /* @@ -843,6 +864,8 @@ fastcall NORET_TYPE void do_exit(long code) for (;;) ; } +EXPORT_SYMBOL_GPL(do_exit); + NORET_TYPE void complete_and_exit(struct completion *comp, long code) { if (comp)