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)));
|
||||
|
||||
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",
|
||||
current->process().name().characters(),
|
||||
current->pid(),
|
||||
|
|
|
@ -246,6 +246,23 @@ void Thread::send_signal(u8 signal, Process* sender)
|
|||
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
|
||||
{
|
||||
return m_pending_signals & ~m_signal_mask;
|
||||
|
@ -330,6 +347,13 @@ bool Thread::should_ignore_signal(u8 signal) const
|
|||
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)
|
||||
{
|
||||
ASSERT_INTERRUPTS_DISABLED();
|
||||
|
|
|
@ -273,6 +273,7 @@ public:
|
|||
void set_selector(u16 s) { m_far_ptr.selector = s; }
|
||||
void set_state(State);
|
||||
|
||||
void send_urgent_signal_to_self(u8 signal);
|
||||
void send_signal(u8 signal, Process* sender);
|
||||
void consider_unblock(time_t now_sec, long now_usec);
|
||||
|
||||
|
@ -283,6 +284,7 @@ public:
|
|||
bool has_unmasked_pending_signals() const;
|
||||
void terminate_due_to_signal(u8 signal);
|
||||
bool should_ignore_signal(u8 signal) const;
|
||||
bool has_signal_handler(u8 signal) const;
|
||||
|
||||
FPUState& fpu_state() { return *m_fpu_state; }
|
||||
bool has_used_fpu() const { return m_has_used_fpu; }
|
||||
|
|
Loading…
Add table
Reference in a new issue