diff options
author | Andreas Kling <awesomekling@gmail.com> | 2018-11-16 21:14:25 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2018-11-16 21:14:25 +0100 |
commit | 6cedb8815380a1f6000fb4a1fed74afa6c32117f (patch) | |
tree | ad68caddf47578e35641b3a23f496c7a9cf0836c /Kernel | |
parent | a788e85c0997cfb50fae0b1ec0b70ef68f461ded (diff) | |
download | serenity-6cedb8815380a1f6000fb4a1fed74afa6c32117f.zip |
Don't unblock a blocked process when it ignores a signal.
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/Process.cpp | 17 | ||||
-rw-r--r-- | Kernel/Process.h | 4 | ||||
-rw-r--r-- | Kernel/Scheduler.cpp | 3 |
3 files changed, 13 insertions, 11 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 5d0b290164..892e2228de 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -745,7 +745,7 @@ bool Process::has_unmasked_pending_signals() const return m_pending_signals & m_signal_mask; } -void Process::dispatch_one_pending_signal() +bool Process::dispatch_one_pending_signal() { ASSERT_INTERRUPTS_DISABLED(); dword signal_candidates = m_pending_signals & m_signal_mask; @@ -757,10 +757,10 @@ void Process::dispatch_one_pending_signal() break; } } - dispatch_signal(signal); + return dispatch_signal(signal); } -void Process::dispatch_signal(byte signal) +bool Process::dispatch_signal(byte signal) { ASSERT_INTERRUPTS_DISABLED(); ASSERT(signal < 32); @@ -774,12 +774,14 @@ void Process::dispatch_signal(byte signal) auto handler_laddr = action.handler_or_sigaction; if (handler_laddr.is_null()) { // FIXME: Is termination really always the appropriate action? - return terminate_due_to_signal(signal); + terminate_due_to_signal(signal); + return true; } + m_pending_signals &= ~(1 << signal); + if (handler_laddr.asPtr() == SIG_IGN) { - dbgprintf("%s(%u) ignored signal %u\n", name().characters(), pid(), signal); - return; + dbgprintf("%s(%u) ignored signal %u\n", name().characters(), pid(), signal); return false; } Scheduler::prepare_to_modify_tss(*this); @@ -871,14 +873,13 @@ void Process::dispatch_signal(byte signal) else push_value_on_stack(m_return_to_ring3_from_signal_trampoline.get()); - m_pending_signals &= ~(1 << signal); - // FIXME: This state is such a hack. It avoids trouble if 'current' is the process receiving a signal. set_state(Skip1SchedulerPass); #ifdef SIGNAL_DEBUG dbgprintf("signal: Okay, %s(%u) {%s} has been primed with signal handler %w:%x\n", name().characters(), pid(), toString(state()), m_tss.cs, m_tss.eip); #endif + return true; } void Process::sys$sigreturn() diff --git a/Kernel/Process.h b/Kernel/Process.h index 18529c57fd..132450e767 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -208,8 +208,8 @@ public: size_t max_open_file_descriptors() const { return m_max_open_file_descriptors; } void send_signal(byte signal, Process* sender); - void dispatch_one_pending_signal(); - void dispatch_signal(byte signal); + bool dispatch_one_pending_signal(); + bool dispatch_signal(byte signal); bool has_unmasked_pending_signals() const; void terminate_due_to_signal(byte signal); diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index 15a2118c88..989ed0cfbb 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -96,7 +96,8 @@ bool Scheduler::pick_next() // syscall effectively being "interrupted" despite having completed? if (process.in_kernel() && !process.is_blocked()) return true; - process.dispatch_one_pending_signal(); + if (!process.dispatch_one_pending_signal()) + return true; if (process.is_blocked()) { process.m_was_interrupted_while_blocked = true; process.unblock(); |