diff options
author | Cristian-Bogdan SIRB <cbsirb@gmail.com> | 2020-02-27 08:40:40 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-02-27 10:09:44 +0100 |
commit | 05ce8586ea257a54717a67fbe20e9dff15a9b0c2 (patch) | |
tree | 3f688110106fe018b72bf15f2494ada25be18451 | |
parent | d28fa89346e2142aae78b535ce4f3b45828ae781 (diff) | |
download | serenity-05ce8586ea257a54717a67fbe20e9dff15a9b0c2.zip |
Kernel: Fix ASSERTION failed in join_thread syscall
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.
-rw-r--r-- | Kernel/Process.cpp | 12 | ||||
-rw-r--r-- | Kernel/Thread.cpp | 1 |
2 files changed, 9 insertions, 4 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 683c71f582..777dff2211 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -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; } } diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index cb20b00083..4502cd569a 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -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; |