X-Git-Url: http://pilppa.org/gitweb/?a=blobdiff_plain;f=fs%2Fexec.c;h=8344ba73a2a670d37d2b08a2587e149490f87eaa;hb=20dbfad8e5dfea56b3cb0cfd4465f01c37b57aa6;hp=49fa0127a33016bbfd52e1d517ea1cc954d32ecd;hpb=7b1c6154fa8bb937e0b1b4f2adbb315d70270f10;p=linux-2.6-omap-h63xx.git diff --git a/fs/exec.c b/fs/exec.c index 49fa0127a33..8344ba73a2a 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -22,7 +22,6 @@ * formats. */ -#include #include #include #include @@ -1371,13 +1370,7 @@ static void format_corename(char *corename, const char *pattern, long signr) static void zap_process(struct task_struct *start) { struct task_struct *t; - unsigned long flags; - /* - * start->sighand can't disappear, but may be - * changed by de_thread() - */ - lock_task_sighand(start, &flags); start->signal->flags = SIGNAL_GROUP_EXIT; start->signal->group_stop_count = 0; @@ -1389,53 +1382,87 @@ static void zap_process(struct task_struct *start) signal_wake_up(t, 1); } } while ((t = next_thread(t)) != start); - - unlock_task_sighand(start, &flags); } -static void zap_threads(struct mm_struct *mm) +static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm, + int exit_code) { struct task_struct *g, *p; - struct task_struct *tsk = current; - struct completion *vfork_done = tsk->vfork_done; + unsigned long flags; + int err = -EAGAIN; - /* - * Make sure nobody is waiting for us to release the VM, - * otherwise we can deadlock when we wait on each other - */ - if (vfork_done) { - tsk->vfork_done = NULL; - complete(vfork_done); + spin_lock_irq(&tsk->sighand->siglock); + if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT)) { + tsk->signal->group_exit_code = exit_code; + zap_process(tsk); + err = 0; } + spin_unlock_irq(&tsk->sighand->siglock); + if (err) + return err; + + if (atomic_read(&mm->mm_users) == mm->core_waiters + 1) + goto done; rcu_read_lock(); for_each_process(g) { + if (g == tsk->group_leader) + continue; + p = g; do { if (p->mm) { - if (p->mm == mm) + if (p->mm == mm) { + /* + * p->sighand can't disappear, but + * may be changed by de_thread() + */ + lock_task_sighand(p, &flags); zap_process(p); + unlock_task_sighand(p, &flags); + } break; } } while ((p = next_thread(p)) != g); } rcu_read_unlock(); +done: + return mm->core_waiters; } -static void coredump_wait(struct mm_struct *mm) +static int coredump_wait(int exit_code) { - DECLARE_COMPLETION(startup_done); + struct task_struct *tsk = current; + struct mm_struct *mm = tsk->mm; + struct completion startup_done; + struct completion *vfork_done; int core_waiters; + init_completion(&mm->core_done); + init_completion(&startup_done); mm->core_startup_done = &startup_done; - zap_threads(mm); - core_waiters = mm->core_waiters; + core_waiters = zap_threads(tsk, mm, exit_code); up_write(&mm->mmap_sem); + if (unlikely(core_waiters < 0)) + goto fail; + + /* + * Make sure nobody is waiting for us to release the VM, + * otherwise we can deadlock when we wait on each other + */ + vfork_done = tsk->vfork_done; + if (vfork_done) { + tsk->vfork_done = NULL; + complete(vfork_done); + } + if (core_waiters) wait_for_completion(&startup_done); +fail: BUG_ON(mm->core_waiters); + return core_waiters; } int do_coredump(long signr, int exit_code, struct pt_regs * regs) @@ -1469,22 +1496,9 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) } mm->dumpable = 0; - retval = -EAGAIN; - spin_lock_irq(¤t->sighand->siglock); - if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) { - current->signal->flags = SIGNAL_GROUP_EXIT; - current->signal->group_exit_code = exit_code; - current->signal->group_stop_count = 0; - retval = 0; - } - spin_unlock_irq(¤t->sighand->siglock); - if (retval) { - up_write(&mm->mmap_sem); + retval = coredump_wait(exit_code); + if (retval < 0) goto fail; - } - - init_completion(&mm->core_done); - coredump_wait(mm); /* * Clear any false indication of pending signals that might