diff --git a/apps/signal-test.cpp b/apps/signal-test.cpp index 3d27491a..9062652c 100644 --- a/apps/signal-test.cpp +++ b/apps/signal-test.cpp @@ -1,20 +1,25 @@ #include #include +#include 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; } diff --git a/kernel/src/arch/x86_64/CPU.cpp b/kernel/src/arch/x86_64/CPU.cpp index 1ac1d957..3b5739c8 100644 --- a/kernel/src/arch/x86_64/CPU.cpp +++ b/kernel/src/arch/x86_64/CPU.cpp @@ -9,6 +9,7 @@ #include "sys/Syscall.h" #include "thread/Scheduler.h" #include "video/TextConsole.h" +#include #include #include #include @@ -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); - u64 cr2; - asm volatile("mov %%cr2, %0" : "=r"(cr2)); - kerrorln("Page fault at RIP %lx while accessing %lx!", regs->rip, cr2); - - decode_page_fault_error_code(regs->error); + 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)) { - // 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); + Scheduler::current()->send_signal(signo); + Scheduler::current()->process_pending_signals(regs); + return; } CPU::efficient_halt(); } -[[noreturn]] void handle_general_protection_fault(Registers* regs) +void handle_page_fault(Registers* regs) { - CPU::disable_interrupts(); + u64 cr2; + asm volatile("mov %%cr2, %0" : "=r"(cr2)); + kerrorln("Page fault while accessing %lx!", cr2); + decode_page_fault_error_code(regs->error); + + handle_cpu_exception(SIGSEGV, nullptr, regs); +} + +void handle_general_protection_fault(Registers* regs) +{ 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"); diff --git a/kernel/src/thread/Thread.cpp b/kernel/src/thread/Thread.cpp index d9b239a5..aa235d46 100644 --- a/kernel/src/thread/Thread.cpp +++ b/kernel/src/thread/Thread.cpp @@ -83,14 +83,18 @@ Result> Thread::resolve_atfile(int dirfd, const String& pa return true; }); - if (parent && parent->state == ThreadState::Waiting) + if (parent) { - auto child = *parent->child_being_waited_for; - if (child == -1 || child == (pid_t)id) + if (parent->state == ThreadState::Waiting) { - parent->child_being_waited_for = (pid_t)id; - parent->wake_up(); + auto child = *parent->child_being_waited_for; + if (child == -1 || child == (pid_t)id) + { + parent->child_being_waited_for = (pid_t)id; + parent->wake_up(); + } } + else { parent->send_signal(SIGCHLD); } } state = ThreadState::Exited;