Commit 56b4c820 authored by Linus Torvalds's avatar Linus Torvalds

wait_task_stopped() must not just return 0 when it has

released the tasklist_lock.

Since it released the lock, the process lists may not
be valid any more, and we must repeat the loop rather than
continue with the next parent.

Use -EAGAIN to show this condition (separate from the
normal -EFAULT that may happen if rusage information could
not be copied to user space).
parent 73d7a5fa
...@@ -1201,8 +1201,15 @@ static int wait_task_stopped(task_t *p, int delayed_group_leader, int noreap, ...@@ -1201,8 +1201,15 @@ static int wait_task_stopped(task_t *p, int delayed_group_leader, int noreap,
write_unlock_irq(&tasklist_lock); write_unlock_irq(&tasklist_lock);
bail_ref: bail_ref:
put_task_struct(p); put_task_struct(p);
read_lock(&tasklist_lock); /*
return 0; * We are returning to the wait loop without having successfully
* removed the process and having released the lock. We cannot
* continue, since the "p" task pointer is potentially stale.
*
* Return -EAGAIN, and do_wait() will restart the loop from the
* beginning. Do _not_ re-acquire the lock.
*/
return -EAGAIN;
} }
/* move to end of parent's list to avoid starvation */ /* move to end of parent's list to avoid starvation */
...@@ -1343,6 +1350,8 @@ static long do_wait(pid_t pid, int options, struct siginfo __user *infop, ...@@ -1343,6 +1350,8 @@ static long do_wait(pid_t pid, int options, struct siginfo __user *infop,
(options & WNOWAIT), (options & WNOWAIT),
infop, infop,
stat_addr, ru); stat_addr, ru);
if (retval == -EAGAIN)
goto repeat;
if (retval != 0) /* He released the lock. */ if (retval != 0) /* He released the lock. */
goto end; goto end;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment