diff --git a/kernel/arch/x86_64/Signal.S b/kernel/arch/x86_64/Signal.S index 1c565d435..865101085 100644 --- a/kernel/arch/x86_64/Signal.S +++ b/kernel/arch/x86_64/Signal.S @@ -43,9 +43,3 @@ signal_trampoline: addq $16, %rsp ret - -.global test_signal -test_signal: - movq $99, %rax - int $0x80 - ret \ No newline at end of file diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 2dd291a75..21ea30553 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -158,6 +158,10 @@ namespace Kernel userspace_info_t m_userspace_info; ExitStatus m_exit_status; + vaddr_t m_signal_handlers[_SIGMAX + 1] { }; + uint64_t m_signal_mask { (1ull << SIGCHLD) | (1ull << SIGURG) }; + static_assert(_SIGMAX < 64); + BAN::UniqPtr m_page_table; BAN::RefPtr m_tty; }; diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 1f8d18b18..25ac48de9 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -15,7 +16,6 @@ #include extern "C" void signal_trampoline(); -extern "C" void test_signal(); namespace Kernel { @@ -795,19 +795,80 @@ namespace Kernel { if (signal < _SIGMIN || signal > _SIGMAX) return BAN::Error::from_errno(EINVAL); - + ASSERT(&Process::current() == this); + // Skip masked (ignored) signals + if (m_signal_mask & (1ull << signal)) + return 0; + LockGuard lock_guard(m_lock); - asm volatile("cli"); + if (m_signal_handlers[signal]) + { + asm volatile("cli"); - uintptr_t* return_rsp_ptr = (uintptr_t*)return_rsp; - *--return_rsp_ptr = return_rip; - *--return_rsp_ptr = signal; - *--return_rsp_ptr = (uintptr_t)test_signal; + uintptr_t* return_rsp_ptr = (uintptr_t*)return_rsp; + *--return_rsp_ptr = return_rip; + *--return_rsp_ptr = signal; + *--return_rsp_ptr = m_signal_handlers[signal]; - return_rsp = (uintptr_t)return_rsp_ptr; - return_rip = (uintptr_t)signal_trampoline; + return_rsp = (uintptr_t)return_rsp_ptr; + return_rip = (uintptr_t)signal_trampoline; + } + else + { + switch (signal) + { + // Abnormal termination of the process with additional actions. + case SIGABRT: + case SIGBUS: + case SIGFPE: + case SIGILL: + case SIGQUIT: + case SIGSEGV: + case SIGSYS: + case SIGTRAP: + case SIGXCPU: + case SIGXFSZ: + // TODO: additional actions + // fall through + + // Abnormal termination of the process + case SIGALRM: + case SIGHUP: + case SIGINT: + case SIGKILL: + case SIGPIPE: + case SIGTERM: + case SIGUSR1: + case SIGUSR2: + case SIGPOLL: + case SIGPROF: + case SIGVTALRM: + { + auto message = BAN::String::formatted("killed by signal {}\n", signal); + (void)m_tty->write(0, message.data(), message.size()); + lock_guard.~LockGuard(); + exit(128 + signal); + ASSERT_NOT_REACHED(); + } + + // Ignore the signal + case SIGCHLD: + case SIGURG: + break; + + // Stop the process: + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + ASSERT_NOT_REACHED(); + + // Continue the process, if it is stopped; otherwise, ignore the signal. + case SIGCONT: + ASSERT_NOT_REACHED(); + } + } return 0; }