Skip to content

Commit

Permalink
Kernel: Fix ASSERTION failed in join_thread syscall
Browse files Browse the repository at this point in the history
set_interrupted_by_death was never called whenever a thread that had
a joiner died, so the joiner remained with the joinee pointer there,
resulting in an assertion fail in JoinBlocker: m_joinee pointed to
a freed task, filled with garbage.

Thread::current->m_joinee may not be valid after the unblock

Properly return the joinee exit value to the joiner thread.
  • Loading branch information
cbsirb authored and awesomekling committed Feb 27, 2020
1 parent d28fa89 commit 05ce858
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 4 deletions.
12 changes: 8 additions & 4 deletions Kernel/Process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3844,10 +3844,14 @@ int Process::sys$join_thread(int tid, void** exit_value)
if (result == Thread::BlockResult::InterruptedByDeath) {
// NOTE: This cleans things up so that Thread::finalize() won't
// get confused about a missing joiner when finalizing the joinee.
InterruptDisabler disabler;
Thread::current->m_joinee->m_joiner = nullptr;
Thread::current->m_joinee = nullptr;
return 0;
InterruptDisabler disabler_t;

if (Thread::current->m_joinee) {
Thread::current->m_joinee->m_joiner = nullptr;
Thread::current->m_joinee = nullptr;
}

break;
}
}

Expand Down
1 change: 1 addition & 0 deletions Kernel/Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ void Thread::finalize()
if (m_joiner) {
ASSERT(m_joiner->m_joinee == this);
static_cast<JoinBlocker*>(m_joiner->m_blocker)->set_joinee_exit_value(m_exit_value);
static_cast<JoinBlocker*>(m_joiner->m_blocker)->set_interrupted_by_death();
m_joiner->m_joinee = nullptr;
// NOTE: We clear the joiner pointer here as well, to be tidy.
m_joiner = nullptr;
Expand Down

0 comments on commit 05ce858

Please sign in to comment.