kernel: Generate signals when children exit / when faults occur
Userspace can now catch segfaults!
This commit is contained in:
parent
60d68b74e1
commit
015419b8f5
@ -1,20 +1,25 @@
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void handler(int)
|
||||
{
|
||||
puts("I'm a signal handler");
|
||||
puts("I caught a segfault!");
|
||||
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigaction(SIGSEGV, &sa, NULL);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = handler;
|
||||
sigaction(SIGABRT, &sa, NULL);
|
||||
sigaction(SIGSEGV, &sa, NULL);
|
||||
|
||||
raise(SIGABRT);
|
||||
|
||||
puts("I'm outside the signal handler!");
|
||||
#pragma GCC diagnostic ignored "-Wnonnull"
|
||||
char* str = nullptr;
|
||||
memset(str, 0, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "sys/Syscall.h"
|
||||
#include "thread/Scheduler.h"
|
||||
#include "video/TextConsole.h"
|
||||
#include <bits/signal.h>
|
||||
#include <cpuid.h>
|
||||
#include <luna/CString.h>
|
||||
#include <luna/CircularQueue.h>
|
||||
@ -70,64 +71,65 @@ void decode_page_fault_error_code(u64 code)
|
||||
(code & PF_RESERVED) ? " | Reserved bits set" : "", (code & PF_NX_VIOLATION) ? " | NX violation" : "");
|
||||
}
|
||||
|
||||
[[noreturn]] void handle_page_fault(Registers* regs)
|
||||
void handle_cpu_exception(int signo, const char* err, Registers* regs)
|
||||
{
|
||||
CPU::disable_interrupts();
|
||||
if (err) kerrorln("Caught CPU exception: %s", err);
|
||||
|
||||
kerrorln("RAX: %.16lx RBX: %.16lx RCX: %.16lx RDX: %.16lx", regs->rax, regs->rbx, regs->rcx, regs->rdx);
|
||||
kerrorln("RBP: %.16lx RSP: %.16lx RDI: %.16lx RSI: %.16lx", regs->rbp, regs->rsp, regs->rdi, regs->rsi);
|
||||
kerrorln("R8: %.16lx R9: %.16lx R10: %.16lx R11: %.16lx", regs->r8, regs->r9, regs->r10, regs->r11);
|
||||
kerrorln("R12: %.16lx R13: %.16lx R14: %.16lx R15: %.16lx", regs->r12, regs->r13, regs->r14, regs->r15);
|
||||
kerrorln("RIP: %.16lx CS: %.16lx SS: %.16lx FLAGS: %.16lx", regs->rip, regs->cs, regs->ss, regs->rflags);
|
||||
|
||||
CPU::print_stack_trace_at(regs);
|
||||
|
||||
if (!is_in_kernel(regs))
|
||||
{
|
||||
Scheduler::current()->send_signal(signo);
|
||||
Scheduler::current()->process_pending_signals(regs);
|
||||
return;
|
||||
}
|
||||
|
||||
CPU::efficient_halt();
|
||||
}
|
||||
|
||||
void handle_page_fault(Registers* regs)
|
||||
{
|
||||
u64 cr2;
|
||||
asm volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||
kerrorln("Page fault at RIP %lx while accessing %lx!", regs->rip, cr2);
|
||||
kerrorln("Page fault while accessing %lx!", cr2);
|
||||
|
||||
decode_page_fault_error_code(regs->error);
|
||||
|
||||
CPU::print_stack_trace_at(regs);
|
||||
|
||||
if (!is_in_kernel(regs))
|
||||
{
|
||||
// FIXME: Kill this process with SIGSEGV once we have signals and all that.
|
||||
kerrorln("Current task %zu was terminated because of a page fault", Scheduler::current()->id);
|
||||
Scheduler::current()->exit_and_signal_parent(127);
|
||||
handle_cpu_exception(SIGSEGV, nullptr, regs);
|
||||
}
|
||||
|
||||
CPU::efficient_halt();
|
||||
}
|
||||
|
||||
[[noreturn]] void handle_general_protection_fault(Registers* regs)
|
||||
void handle_general_protection_fault(Registers* regs)
|
||||
{
|
||||
CPU::disable_interrupts();
|
||||
|
||||
kerrorln("General protection fault at RIP %lx, error code %lx!", regs->rip, regs->error);
|
||||
|
||||
CPU::print_stack_trace_at(regs);
|
||||
|
||||
if (!is_in_kernel(regs))
|
||||
{
|
||||
// FIXME: Kill this process with SIGSEGV once we have signals and all that.
|
||||
kerrorln("Current task %zu was terminated because of a general protection fault", Scheduler::current()->id);
|
||||
Scheduler::current()->exit_and_signal_parent(127);
|
||||
}
|
||||
|
||||
CPU::efficient_halt();
|
||||
handle_cpu_exception(SIGSEGV, nullptr, regs);
|
||||
}
|
||||
|
||||
extern "C" void handle_x86_exception(Registers* regs)
|
||||
{
|
||||
CPU::disable_interrupts();
|
||||
switch (regs->isr)
|
||||
{
|
||||
case 0: FIXME_UNHANDLED_INTERRUPT("Division by zero");
|
||||
case 0: handle_cpu_exception(SIGFPE, "Division by zero", regs); return;
|
||||
case 1: FIXME_UNHANDLED_INTERRUPT("Debug interrupt");
|
||||
case 2: FIXME_UNHANDLED_INTERRUPT("NMI (Non-maskable interrupt)");
|
||||
case 3: FIXME_UNHANDLED_INTERRUPT("Breakpoint");
|
||||
case 4: FIXME_UNHANDLED_INTERRUPT("Overflow");
|
||||
case 5: FIXME_UNHANDLED_INTERRUPT("Bound range exceeded");
|
||||
case 6: FIXME_UNHANDLED_INTERRUPT("Invalid opcode");
|
||||
case 6: handle_cpu_exception(SIGILL, "Invalid opcode", regs); return;
|
||||
case 7: FIXME_UNHANDLED_INTERRUPT("Device not available");
|
||||
case 10: FIXME_UNHANDLED_INTERRUPT("Invalid TSS");
|
||||
case 11: FIXME_UNHANDLED_INTERRUPT("Segment not present");
|
||||
case 12: FIXME_UNHANDLED_INTERRUPT("Stack-segment fault");
|
||||
case 13: handle_general_protection_fault(regs);
|
||||
case 14: handle_page_fault(regs);
|
||||
case 16: FIXME_UNHANDLED_INTERRUPT("x87 floating-point exception");
|
||||
case 13: handle_general_protection_fault(regs); return;
|
||||
case 14: handle_page_fault(regs); return;
|
||||
case 16: handle_cpu_exception(SIGFPE, "x87 floating-point exception", regs); return;
|
||||
case 17: FIXME_UNHANDLED_INTERRUPT("Alignment check");
|
||||
case 19: FIXME_UNHANDLED_INTERRUPT("SIMD floating-point exception");
|
||||
case 20: FIXME_UNHANDLED_INTERRUPT("Virtualization exception");
|
||||
|
@ -83,7 +83,9 @@ Result<SharedPtr<VFS::Inode>> Thread::resolve_atfile(int dirfd, const String& pa
|
||||
return true;
|
||||
});
|
||||
|
||||
if (parent && parent->state == ThreadState::Waiting)
|
||||
if (parent)
|
||||
{
|
||||
if (parent->state == ThreadState::Waiting)
|
||||
{
|
||||
auto child = *parent->child_being_waited_for;
|
||||
if (child == -1 || child == (pid_t)id)
|
||||
@ -92,6 +94,8 @@ Result<SharedPtr<VFS::Inode>> Thread::resolve_atfile(int dirfd, const String& pa
|
||||
parent->wake_up();
|
||||
}
|
||||
}
|
||||
else { parent->send_signal(SIGCHLD); }
|
||||
}
|
||||
|
||||
state = ThreadState::Exited;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user