Messages in this thread Patch in this message | | | Date | Mon, 9 Feb 2009 06:14:00 +0100 | From | Oleg Nesterov <> | Subject | Re: main thread pthread_exit/sys_exit bug! |
| |
On 02/09, Oleg Nesterov wrote: > > Yes sure. I meant, instead of just checking task_is_stopped_or_traced() in > wait_consider_task(), we should do somthing like
In short, please see the "patch" below. I doubt it can be compiled, just for the illustration.
Oleg.
--- a/kernel/exit.c +++ b/kernel/exit.c @@ -1417,6 +1417,19 @@ static int wait_task_zombie(struct task_ return retval; } +static int *wait_xxx(struct task_struct *p, int ptrace) +{ + if (ptrace) { + if (task_is_stopped_or_traced(p)) + return &p->exit_code; + } else { + if (p->signal->flags & SIGNAL_STOPPED_STOPPED) + return &p->signal->group_exit_code; + } + + return NULL; +} + /* * Handle sys_wait4 work for one task in state TASK_STOPPED. We hold * read_lock(&tasklist_lock) on entry. If we return zero, we still hold @@ -1427,7 +1440,7 @@ static int wait_task_stopped(int ptrace, int options, struct siginfo __user *infop, int __user *stat_addr, struct rusage __user *ru) { - int retval, exit_code, why; + int retval, exit_code, *p_code, why; uid_t uid = 0; /* unneeded, required by compiler */ pid_t pid; @@ -1437,22 +1450,16 @@ static int wait_task_stopped(int ptrace, exit_code = 0; spin_lock_irq(&p->sighand->siglock); - if (unlikely(!task_is_stopped_or_traced(p))) - goto unlock_sig; - - if (!ptrace && p->signal->group_stop_count > 0) - /* - * A group stop is in progress and this is the group leader. - * We won't report until all threads have stopped. - */ + p_code = wait_xxx(p, ptrace); + if (unlikely(!p_code)) goto unlock_sig; - exit_code = p->exit_code; + exit_code = *p_code; if (!exit_code) goto unlock_sig; if (!unlikely(options & WNOWAIT)) - p->exit_code = 0; + *p_code = 0; /* don't need the RCU readlock here as we're holding a spinlock */ uid = __task_cred(p)->uid; @@ -1608,7 +1615,7 @@ static int wait_consider_task(struct tas */ *notask_error = 0; - if (task_is_stopped_or_traced(p)) + if (wait_xxx(p, ptrace)) return wait_task_stopped(ptrace, p, options, infop, stat_addr, ru);
| |