From 6d1144bbcabb6f9c3033faed8ef1000f905c8573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 25 Apr 2007 08:25:10 +0000 Subject: [PATCH] The thread context was destructed a bit too early: if a team was killed (or didn't close all of its file descriptors), code outside of the core kernel would be executed in the descriptor's close/free hooks. Since the semaphore timeout code, and send_data()/receive_data() rely on the thread being available in the thread hash, they wouldn't work anymore. This fixes bug #1168. Thanks to Marcus for providing such a nice test case :-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20808 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/thread.c | 76 +++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 43 deletions(-) diff --git a/src/system/kernel/thread.c b/src/system/kernel/thread.c index b7c1802bd8..3eab7665ad 100644 --- a/src/system/kernel/thread.c +++ b/src/system/kernel/thread.c @@ -933,35 +933,6 @@ thread_exit(void) // boost our priority to get this over with thread->priority = thread->next_priority = B_URGENT_DISPLAY_PRIORITY; - // Stop debugging for this thread - state = disable_interrupts(); - GRAB_THREAD_LOCK(); - - debugInfo = thread->debug_info; - clear_thread_debug_info(&thread->debug_info, true); - - RELEASE_THREAD_LOCK(); - restore_interrupts(state); - - destroy_thread_debug_info(&debugInfo); - - // shutdown the thread messaging - - status = acquire_sem_etc(thread->msg.write_sem, 1, B_RELATIVE_TIMEOUT, 0); - if (status == B_WOULD_BLOCK) { - // there is data waiting for us, so let us eat it - thread_id sender; - - delete_sem(thread->msg.write_sem); - // first, let's remove all possibly waiting writers - receive_data_etc(&sender, NULL, 0, B_RELATIVE_TIMEOUT); - } else { - // we probably own the semaphore here, and we're the last to do so - delete_sem(thread->msg.write_sem); - } - // now we can safely remove the msg.read_sem - delete_sem(thread->msg.read_sem); - // Cancel previously installed alarm timer, if any cancel_timer(&thread->alarm); @@ -1005,10 +976,6 @@ thread_exit(void) cachedDeathSem = team->death_sem; - // remove thread from hash, so it's no longer accessible - hash_remove(sThreadHash, thread); - sUsedThreads--; - if (deleteTeam) { struct team *parent = team->parent; @@ -1047,16 +1014,6 @@ thread_exit(void) restore_interrupts(state); TRACE(("thread_exit: thread 0x%lx now a kernel thread!\n", thread->id)); - } else { - // for kernel threads, we don't need to care about their death entries - state = disable_interrupts(); - GRAB_THREAD_LOCK(); - - hash_remove(sThreadHash, thread); - sUsedThreads--; - - RELEASE_THREAD_LOCK(); - restore_interrupts(state); } // delete the team if we're its main thread @@ -1072,6 +1029,39 @@ thread_exit(void) cachedDeathSem = -1; } + state = disable_interrupts(); + GRAB_THREAD_LOCK(); + + // remove thread from hash, so it's no longer accessible + hash_remove(sThreadHash, thread); + sUsedThreads--; + + // Stop debugging for this thread + debugInfo = thread->debug_info; + clear_thread_debug_info(&thread->debug_info, true); + + RELEASE_THREAD_LOCK(); + restore_interrupts(state); + + destroy_thread_debug_info(&debugInfo); + + // shutdown the thread messaging + + status = acquire_sem_etc(thread->msg.write_sem, 1, B_RELATIVE_TIMEOUT, 0); + if (status == B_WOULD_BLOCK) { + // there is data waiting for us, so let us eat it + thread_id sender; + + delete_sem(thread->msg.write_sem); + // first, let's remove all possibly waiting writers + receive_data_etc(&sender, NULL, 0, B_RELATIVE_TIMEOUT); + } else { + // we probably own the semaphore here, and we're the last to do so + delete_sem(thread->msg.write_sem); + } + // now we can safely remove the msg.read_sem + delete_sem(thread->msg.read_sem); + // fill all death entries and delete the sem that others will use to wait on us { sem_id cachedExitSem = thread->exit.sem;