From: Kirill Korotaev <dev@sw.ru>

Note, that during exit process there can be a thread in the system with
tsk->sighand == NULL, since the following call trace:

release_task()
{
	....
	__exit_sighand()	<<< makes tsk->sighand == NULL;
	__unhash_process()	<<< unhashes thread
	....
}

next, we see that next_thread checks for tsk->sighand != NULL:

task_t fastcall *next_thread(const task_t *p)
{
  #ifdef CONFIG_SMP
        if (!p->sighand)
                BUG();		<<< BUG happened here!!!
        if (!spin_is_locked(&p->sighand->siglock) &&
                                !rwlock_is_locked(&tasklist_lock))
	....
}

So the question is why next_thread() should check for (p->sighand != NULL)
&& spin_is_locked(&p->sighand->siglock)?

I think these checks are invalid.  For example do_task_stat() (which called
next_thread() in this BUG) checks for tsk->sighand != NULL explicitly.

And moreover, next_thread() DOES always works correctly, whether there are
threads or none.

This patch removes sighand checks from the next_thread(), since they are
incorrect and has nothing to do with the next_thread() function.  So they
could trigger BUG() when there were no actually bug at all.

Signed-Off-By: Kirill Korotaev <dev@sw.ru>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/kernel/exit.c |    5 +----
 1 files changed, 1 insertion(+), 4 deletions(-)

diff -puN kernel/exit.c~next_thread-bug-fixes kernel/exit.c
--- 25/kernel/exit.c~next_thread-bug-fixes	2004-09-13 01:01:22.227228320 -0700
+++ 25-akpm/kernel/exit.c	2004-09-13 01:01:22.231227712 -0700
@@ -857,10 +857,7 @@ asmlinkage long sys_exit(int error_code)
 task_t fastcall *next_thread(const task_t *p)
 {
 #ifdef CONFIG_SMP
-	if (!p->sighand)
-		BUG();
-	if (!spin_is_locked(&p->sighand->siglock) &&
-				!rwlock_is_locked(&tasklist_lock))
+	if (!rwlock_is_locked(&tasklist_lock))
 		BUG();
 #endif
 	return pid_task(p->pids[PIDTYPE_TGID].pid_list.next, PIDTYPE_TGID);
_