Kernel: Send SIGSEGV on seg-fault
Now programs can catch the SIGSEGV signal when they segfault. This commit also introduced the send_urgent_signal_to_self method, which is needed to send signals to a thread when handling exceptions caused by the same thread.
This commit is contained in:
parent
7fc903b97a
commit
c136fd3fe2
Notes:
sideshowbarker
2024-07-19 11:45:46 +09:00
Author: https://github.com/DrewStratford Commit: https://github.com/SerenityOS/serenity/commit/c136fd3fe22 Pull-request: https://github.com/SerenityOS/serenity/pull/637 Reviewed-by: https://github.com/awesomekling
3 changed files with 31 additions and 0 deletions
|
@ -262,6 +262,11 @@ void exception_14_handler(RegisterDump& regs)
|
||||||
auto response = MM.handle_page_fault(PageFault(regs.exception_code, VirtualAddress(fault_address)));
|
auto response = MM.handle_page_fault(PageFault(regs.exception_code, VirtualAddress(fault_address)));
|
||||||
|
|
||||||
if (response == PageFaultResponse::ShouldCrash) {
|
if (response == PageFaultResponse::ShouldCrash) {
|
||||||
|
if(current->has_signal_handler(SIGSEGV)){
|
||||||
|
current->send_urgent_signal_to_self(SIGSEGV);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
kprintf("\033[31;1m%s(%u:%u) Unrecoverable page fault, %s address %p\033[0m\n",
|
kprintf("\033[31;1m%s(%u:%u) Unrecoverable page fault, %s address %p\033[0m\n",
|
||||||
current->process().name().characters(),
|
current->process().name().characters(),
|
||||||
current->pid(),
|
current->pid(),
|
||||||
|
|
|
@ -246,6 +246,23 @@ void Thread::send_signal(u8 signal, Process* sender)
|
||||||
m_pending_signals |= 1 << (signal - 1);
|
m_pending_signals |= 1 << (signal - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Certain exceptions, such as SIGSEGV and SIGILL, put a
|
||||||
|
// thread into a state where the signal handler must be
|
||||||
|
// invoked immediately, otherwise it will continue to fault.
|
||||||
|
// This function should be used in an exception handler to
|
||||||
|
// ensure that when the thread resumes, it's executing in
|
||||||
|
// the appropriate signal handler.
|
||||||
|
void Thread::send_urgent_signal_to_self(u8 signal)
|
||||||
|
{
|
||||||
|
// FIXME: because of a bug in dispatch_signal we can't
|
||||||
|
// setup a signal while we are the current thread. Because of
|
||||||
|
// this we use a work-around where we send the signal and then
|
||||||
|
// block, allowing the scheduler to properly dispatch the signal
|
||||||
|
// before the thread is next run.
|
||||||
|
send_signal(signal, &process());
|
||||||
|
(void)block<SemiPermanentBlocker>(SemiPermanentBlocker::Reason::Signal);
|
||||||
|
}
|
||||||
|
|
||||||
bool Thread::has_unmasked_pending_signals() const
|
bool Thread::has_unmasked_pending_signals() const
|
||||||
{
|
{
|
||||||
return m_pending_signals & ~m_signal_mask;
|
return m_pending_signals & ~m_signal_mask;
|
||||||
|
@ -330,6 +347,13 @@ bool Thread::should_ignore_signal(u8 signal) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Thread::has_signal_handler(u8 signal) const
|
||||||
|
{
|
||||||
|
ASSERT(signal < 32);
|
||||||
|
auto& action = m_signal_action_data[signal];
|
||||||
|
return !action.handler_or_sigaction.is_null();
|
||||||
|
}
|
||||||
|
|
||||||
ShouldUnblockThread Thread::dispatch_signal(u8 signal)
|
ShouldUnblockThread Thread::dispatch_signal(u8 signal)
|
||||||
{
|
{
|
||||||
ASSERT_INTERRUPTS_DISABLED();
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
|
|
|
@ -273,6 +273,7 @@ public:
|
||||||
void set_selector(u16 s) { m_far_ptr.selector = s; }
|
void set_selector(u16 s) { m_far_ptr.selector = s; }
|
||||||
void set_state(State);
|
void set_state(State);
|
||||||
|
|
||||||
|
void send_urgent_signal_to_self(u8 signal);
|
||||||
void send_signal(u8 signal, Process* sender);
|
void send_signal(u8 signal, Process* sender);
|
||||||
void consider_unblock(time_t now_sec, long now_usec);
|
void consider_unblock(time_t now_sec, long now_usec);
|
||||||
|
|
||||||
|
@ -283,6 +284,7 @@ public:
|
||||||
bool has_unmasked_pending_signals() const;
|
bool has_unmasked_pending_signals() const;
|
||||||
void terminate_due_to_signal(u8 signal);
|
void terminate_due_to_signal(u8 signal);
|
||||||
bool should_ignore_signal(u8 signal) const;
|
bool should_ignore_signal(u8 signal) const;
|
||||||
|
bool has_signal_handler(u8 signal) const;
|
||||||
|
|
||||||
FPUState& fpu_state() { return *m_fpu_state; }
|
FPUState& fpu_state() { return *m_fpu_state; }
|
||||||
bool has_used_fpu() const { return m_has_used_fpu; }
|
bool has_used_fpu() const { return m_has_used_fpu; }
|
||||||
|
|
Loading…
Add table
Reference in a new issue