From: Rusty Russell <rusty@rustcorp.com.au>

Vatsa found this race: waitpid might not actually succeed, if another
(unrelated) child thread has exited while we're waiting for the kthread (in
this case waitpid returns -ERESTARTSYS).  The answer it to wait for
*everyone*, flush_signals, and if it's not the child we wanted, loop.



---

 kernel/kthread.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletion(-)

diff -puN kernel/kthread.c~kthread_stop-race-fix kernel/kthread.c
--- 25/kernel/kthread.c~kthread_stop-race-fix	2004-02-02 00:29:17.000000000 -0800
+++ 25-akpm/kernel/kthread.c	2004-02-02 00:29:17.000000000 -0800
@@ -104,7 +104,10 @@ static void keventd_stop_kthread(void *_
 	adopt_kthread(stop->k);
 	/* All signals are blocked, hence the force. */
 	force_sig(SIGTERM, stop->k);
-	waitpid(stop->k->tgid, &status, __WALL);
+	/* Other threads might exit: if we ask for one pid that
+	 * returns -ERESTARTSYS. */
+	while (waitpid(-1, &status, __WALL) != stop->k->tgid)
+		flush_signals(current);
 	stop->result = -((status >> 8) & 0xFF);
 	complete(&stop->done);
 

_