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:
+33
-43
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user