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
This commit is contained in:
Axel Dörfler
2007-04-25 08:25:10 +00:00
parent 895eb46bc4
commit 6d1144bbca
+33 -43
View File
@@ -933,35 +933,6 @@ thread_exit(void)
// boost our priority to get this over with // boost our priority to get this over with
thread->priority = thread->next_priority = B_URGENT_DISPLAY_PRIORITY; 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 previously installed alarm timer, if any
cancel_timer(&thread->alarm); cancel_timer(&thread->alarm);
@@ -1005,10 +976,6 @@ thread_exit(void)
cachedDeathSem = team->death_sem; cachedDeathSem = team->death_sem;
// remove thread from hash, so it's no longer accessible
hash_remove(sThreadHash, thread);
sUsedThreads--;
if (deleteTeam) { if (deleteTeam) {
struct team *parent = team->parent; struct team *parent = team->parent;
@@ -1047,16 +1014,6 @@ thread_exit(void)
restore_interrupts(state); restore_interrupts(state);
TRACE(("thread_exit: thread 0x%lx now a kernel thread!\n", thread->id)); 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 // delete the team if we're its main thread
@@ -1072,6 +1029,39 @@ thread_exit(void)
cachedDeathSem = -1; 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 // fill all death entries and delete the sem that others will use to wait on us
{ {
sem_id cachedExitSem = thread->exit.sem; sem_id cachedExitSem = thread->exit.sem;