diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 94879feb834..addcb91efba 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1464,7 +1464,7 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options) } } - m_waitee = waitee; + m_waitee_pid = waitee; block(BlockedWait); sched_yield(); if (m_was_interrupted_while_blocked) @@ -1472,17 +1472,20 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options) Process* waitee_process; { InterruptDisabler disabler; - // NOTE: If waitee was -1, m_waitee will have been filled in by the scheduler. - waitee_process = Process::from_pid(m_waitee); + waitee_process = Process::from_pid(m_waitee_pid); } ASSERT(waitee_process); exit_status = reap(*waitee_process); - return m_waitee; + return m_waitee_pid; } void Process::unblock() { + if (current == this) { + kprintf("ignoring unblock() on current, %s(%u) {%s}\n", name().characters(), pid(), toString(state())); + return; + } ASSERT(m_state != Process::Runnable && m_state != Process::Running); system.nblocked--; m_state = Process::Runnable; diff --git a/Kernel/Process.h b/Kernel/Process.h index f64705765e7..02a2fdc80c5 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -187,7 +187,7 @@ public: void did_schedule() { ++m_timesScheduled; } dword timesScheduled() const { return m_timesScheduled; } - pid_t waitee() const { return m_waitee; } + pid_t waitee_pid() const { return m_waitee_pid; } dword framePtr() const { return m_tss.ebp; } dword stackPtr() const { return m_tss.esp; } @@ -265,7 +265,7 @@ private: int m_error { 0 }; void* m_kernelStack { nullptr }; dword m_timesScheduled { 0 }; - pid_t m_waitee { -1 }; + pid_t m_waitee_pid { -1 }; int m_fdBlockedOnRead { -1 }; int m_blocked_fd { -1 }; size_t m_max_open_file_descriptors { 16 }; diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index c2471dfbe7c..361f387e1ea 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -38,8 +38,8 @@ bool Scheduler::pick_next() process.for_each_child([&process] (Process& child) { if (child.state() != Process::Dead) return true; - if (process.waitee() == -1 || process.waitee() == child.pid()) { - process.m_waitee = child.pid(); + if (process.waitee_pid() == -1 || process.waitee_pid() == child.pid()) { + process.m_waitee_pid = child.pid(); process.unblock(); return false; } @@ -99,9 +99,12 @@ bool Scheduler::pick_next() // syscall effectively being "interrupted" despite having completed? if (process.in_kernel() && !process.is_blocked()) return true; + // NOTE: dispatch_one_pending_signal() may unblock the process. + bool was_blocked = process.is_blocked(); if (!process.dispatch_one_pending_signal()) return true; - if (process.is_blocked()) { + if (was_blocked) { + dbgprintf("Unblock %s(%u) due to signal\n", process.name().characters(), process.pid()); process.m_was_interrupted_while_blocked = true; process.unblock(); }