summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCristian-Bogdan SIRB <cbsirb@gmail.com>2020-02-27 08:40:40 +0200
committerAndreas Kling <kling@serenityos.org>2020-02-27 10:09:44 +0100
commit05ce8586ea257a54717a67fbe20e9dff15a9b0c2 (patch)
tree3f688110106fe018b72bf15f2494ada25be18451
parentd28fa89346e2142aae78b535ce4f3b45828ae781 (diff)
downloadserenity-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.cpp12
-rw-r--r--Kernel/Thread.cpp1
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;