summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-11-16 21:14:25 +0100
committerAndreas Kling <awesomekling@gmail.com>2018-11-16 21:14:25 +0100
commit6cedb8815380a1f6000fb4a1fed74afa6c32117f (patch)
treead68caddf47578e35641b3a23f496c7a9cf0836c /Kernel
parenta788e85c0997cfb50fae0b1ec0b70ef68f461ded (diff)
downloadserenity-6cedb8815380a1f6000fb4a1fed74afa6c32117f.zip
Don't unblock a blocked process when it ignores a signal.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Process.cpp17
-rw-r--r--Kernel/Process.h4
-rw-r--r--Kernel/Scheduler.cpp3
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();