Compare commits
No commits in common. "8066e8f1d82503834847b25543e556e774396135" and "cde467ee465cd821a71f068bfd89a6f6100d0175" have entirely different histories.
8066e8f1d8
...
cde467ee46
@ -1,25 +1,20 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
void handler(int)
|
void handler(int)
|
||||||
{
|
{
|
||||||
puts("I caught a segfault!");
|
puts("I'm a signal handler");
|
||||||
|
|
||||||
struct sigaction sa;
|
|
||||||
sa.sa_handler = SIG_DFL;
|
|
||||||
sigaction(SIGSEGV, &sa, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
sa.sa_handler = handler;
|
sa.sa_handler = handler;
|
||||||
sigaction(SIGSEGV, &sa, NULL);
|
sigaction(SIGABRT, &sa, NULL);
|
||||||
|
|
||||||
#pragma GCC diagnostic ignored "-Wnonnull"
|
raise(SIGABRT);
|
||||||
char* str = nullptr;
|
|
||||||
memset(str, 0, 2);
|
puts("I'm outside the signal handler!");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
#include "video/TextConsole.h"
|
#include "video/TextConsole.h"
|
||||||
#include <bits/signal.h>
|
|
||||||
#include <cpuid.h>
|
#include <cpuid.h>
|
||||||
#include <luna/CString.h>
|
#include <luna/CString.h>
|
||||||
#include <luna/CircularQueue.h>
|
#include <luna/CircularQueue.h>
|
||||||
@ -71,65 +70,64 @@ void decode_page_fault_error_code(u64 code)
|
|||||||
(code & PF_RESERVED) ? " | Reserved bits set" : "", (code & PF_NX_VIOLATION) ? " | NX violation" : "");
|
(code & PF_RESERVED) ? " | Reserved bits set" : "", (code & PF_NX_VIOLATION) ? " | NX violation" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_cpu_exception(int signo, const char* err, Registers* regs)
|
[[noreturn]] void handle_page_fault(Registers* regs)
|
||||||
{
|
{
|
||||||
if (err) kerrorln("Caught CPU exception: %s", err);
|
CPU::disable_interrupts();
|
||||||
|
|
||||||
kerrorln("RAX: %.16lx RBX: %.16lx RCX: %.16lx RDX: %.16lx", regs->rax, regs->rbx, regs->rcx, regs->rdx);
|
u64 cr2;
|
||||||
kerrorln("RBP: %.16lx RSP: %.16lx RDI: %.16lx RSI: %.16lx", regs->rbp, regs->rsp, regs->rdi, regs->rsi);
|
asm volatile("mov %%cr2, %0" : "=r"(cr2));
|
||||||
kerrorln("R8: %.16lx R9: %.16lx R10: %.16lx R11: %.16lx", regs->r8, regs->r9, regs->r10, regs->r11);
|
kerrorln("Page fault at RIP %lx while accessing %lx!", regs->rip, cr2);
|
||||||
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);
|
decode_page_fault_error_code(regs->error);
|
||||||
|
|
||||||
CPU::print_stack_trace_at(regs);
|
CPU::print_stack_trace_at(regs);
|
||||||
|
|
||||||
if (!is_in_kernel(regs))
|
if (!is_in_kernel(regs))
|
||||||
{
|
{
|
||||||
Scheduler::current()->send_signal(signo);
|
// FIXME: Kill this process with SIGSEGV once we have signals and all that.
|
||||||
Scheduler::current()->process_pending_signals(regs);
|
kerrorln("Current task %zu was terminated because of a page fault", Scheduler::current()->id);
|
||||||
return;
|
Scheduler::current()->exit_and_signal_parent(127);
|
||||||
}
|
}
|
||||||
|
|
||||||
CPU::efficient_halt();
|
CPU::efficient_halt();
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_page_fault(Registers* regs)
|
[[noreturn]] void handle_general_protection_fault(Registers* regs)
|
||||||
{
|
{
|
||||||
u64 cr2;
|
CPU::disable_interrupts();
|
||||||
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);
|
kerrorln("General protection fault at RIP %lx, error code %lx!", regs->rip, regs->error);
|
||||||
|
|
||||||
handle_cpu_exception(SIGSEGV, nullptr, regs);
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void handle_x86_exception(Registers* regs)
|
extern "C" void handle_x86_exception(Registers* regs)
|
||||||
{
|
{
|
||||||
CPU::disable_interrupts();
|
|
||||||
switch (regs->isr)
|
switch (regs->isr)
|
||||||
{
|
{
|
||||||
case 0: handle_cpu_exception(SIGFPE, "Division by zero", regs); return;
|
case 0: FIXME_UNHANDLED_INTERRUPT("Division by zero");
|
||||||
case 1: FIXME_UNHANDLED_INTERRUPT("Debug interrupt");
|
case 1: FIXME_UNHANDLED_INTERRUPT("Debug interrupt");
|
||||||
case 2: FIXME_UNHANDLED_INTERRUPT("NMI (Non-maskable interrupt)");
|
case 2: FIXME_UNHANDLED_INTERRUPT("NMI (Non-maskable interrupt)");
|
||||||
case 3: FIXME_UNHANDLED_INTERRUPT("Breakpoint");
|
case 3: FIXME_UNHANDLED_INTERRUPT("Breakpoint");
|
||||||
case 4: FIXME_UNHANDLED_INTERRUPT("Overflow");
|
case 4: FIXME_UNHANDLED_INTERRUPT("Overflow");
|
||||||
case 5: FIXME_UNHANDLED_INTERRUPT("Bound range exceeded");
|
case 5: FIXME_UNHANDLED_INTERRUPT("Bound range exceeded");
|
||||||
case 6: handle_cpu_exception(SIGILL, "Invalid opcode", regs); return;
|
case 6: FIXME_UNHANDLED_INTERRUPT("Invalid opcode");
|
||||||
case 7: FIXME_UNHANDLED_INTERRUPT("Device not available");
|
case 7: FIXME_UNHANDLED_INTERRUPT("Device not available");
|
||||||
case 10: FIXME_UNHANDLED_INTERRUPT("Invalid TSS");
|
case 10: FIXME_UNHANDLED_INTERRUPT("Invalid TSS");
|
||||||
case 11: FIXME_UNHANDLED_INTERRUPT("Segment not present");
|
case 11: FIXME_UNHANDLED_INTERRUPT("Segment not present");
|
||||||
case 12: FIXME_UNHANDLED_INTERRUPT("Stack-segment fault");
|
case 12: FIXME_UNHANDLED_INTERRUPT("Stack-segment fault");
|
||||||
case 13: handle_general_protection_fault(regs); return;
|
case 13: handle_general_protection_fault(regs);
|
||||||
case 14: handle_page_fault(regs); return;
|
case 14: handle_page_fault(regs);
|
||||||
case 16: handle_cpu_exception(SIGFPE, "x87 floating-point exception", regs); return;
|
case 16: FIXME_UNHANDLED_INTERRUPT("x87 floating-point exception");
|
||||||
case 17: FIXME_UNHANDLED_INTERRUPT("Alignment check");
|
case 17: FIXME_UNHANDLED_INTERRUPT("Alignment check");
|
||||||
case 19: FIXME_UNHANDLED_INTERRUPT("SIMD floating-point exception");
|
case 19: FIXME_UNHANDLED_INTERRUPT("SIMD floating-point exception");
|
||||||
case 20: FIXME_UNHANDLED_INTERRUPT("Virtualization exception");
|
case 20: FIXME_UNHANDLED_INTERRUPT("Virtualization exception");
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include "memory/MemoryManager.h"
|
#include "memory/MemoryManager.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
#include <bits/signal.h>
|
|
||||||
|
|
||||||
Result<u64> sys_sigreturn(Registers* regs, SyscallArgs)
|
Result<u64> sys_sigreturn(Registers* regs, SyscallArgs)
|
||||||
{
|
{
|
||||||
@ -67,33 +66,3 @@ Result<u64> sys_kill(Registers*, SyscallArgs args)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> sys_sigprocmask(Registers*, SyscallArgs args)
|
|
||||||
{
|
|
||||||
auto* current = Scheduler::current();
|
|
||||||
|
|
||||||
int how = (int)args[0];
|
|
||||||
const sigset_t* set = (const sigset_t*)args[1];
|
|
||||||
sigset_t* oldset = (sigset_t*)args[2];
|
|
||||||
|
|
||||||
if (oldset)
|
|
||||||
{
|
|
||||||
if (!MemoryManager::copy_to_user_typed(oldset, ¤t->signal_mask)) return err(EFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (set)
|
|
||||||
{
|
|
||||||
sigset_t kset;
|
|
||||||
if (!MemoryManager::copy_from_user_typed(set, &kset)) return err(EFAULT);
|
|
||||||
|
|
||||||
switch (how)
|
|
||||||
{
|
|
||||||
case SIG_BLOCK: current->signal_mask |= kset;
|
|
||||||
case SIG_UNBLOCK: current->signal_mask &= ~kset;
|
|
||||||
case SIG_SETMASK: current->signal_mask = kset;
|
|
||||||
default: return err(EINVAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
#include <bits/atfile.h>
|
#include <bits/atfile.h>
|
||||||
#include <bits/open-flags.h>
|
#include <bits/open-flags.h>
|
||||||
#include <bits/signal.h>
|
|
||||||
#include <bits/waitpid.h>
|
#include <bits/waitpid.h>
|
||||||
#include <luna/Alloc.h>
|
#include <luna/Alloc.h>
|
||||||
#include <luna/Atomic.h>
|
#include <luna/Atomic.h>
|
||||||
@ -83,18 +82,14 @@ Result<SharedPtr<VFS::Inode>> Thread::resolve_atfile(int dirfd, const String& pa
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (parent)
|
if (parent && parent->state == ThreadState::Waiting)
|
||||||
{
|
{
|
||||||
if (parent->state == ThreadState::Waiting)
|
auto child = *parent->child_being_waited_for;
|
||||||
|
if (child == -1 || child == (pid_t)id)
|
||||||
{
|
{
|
||||||
auto child = *parent->child_being_waited_for;
|
parent->child_being_waited_for = (pid_t)id;
|
||||||
if (child == -1 || child == (pid_t)id)
|
parent->wake_up();
|
||||||
{
|
|
||||||
parent->child_being_waited_for = (pid_t)id;
|
|
||||||
parent->wake_up();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else { parent->send_signal(SIGCHLD); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state = ThreadState::Exited;
|
state = ThreadState::Exited;
|
||||||
@ -111,40 +106,26 @@ enum class DefaultSignalAction
|
|||||||
};
|
};
|
||||||
|
|
||||||
static constexpr DefaultSignalAction default_actions[] = {
|
static constexpr DefaultSignalAction default_actions[] = {
|
||||||
DefaultSignalAction::Terminate, // SIGHUP
|
DefaultSignalAction::Terminate // SIGABRT
|
||||||
DefaultSignalAction::Terminate, // SIGINT
|
|
||||||
DefaultSignalAction::Terminate, // SIGQUIT (dump core)
|
|
||||||
DefaultSignalAction::Terminate, // SIGILL (dump core)
|
|
||||||
DefaultSignalAction::Terminate, // SIGTRAP (dump core)
|
|
||||||
DefaultSignalAction::Terminate, // SIGABRT (dump core)
|
|
||||||
DefaultSignalAction::Ignore, // SIGCHLD
|
|
||||||
DefaultSignalAction::Terminate, // SIGFPE (dump core)
|
|
||||||
DefaultSignalAction::Terminate, // SIGKILL
|
|
||||||
DefaultSignalAction::Terminate, // SIGSTOP (FIXME: Support stopping and continuing)
|
|
||||||
DefaultSignalAction::Terminate, // SIGSEGV (dump core)
|
|
||||||
DefaultSignalAction::Ignore, // SIGCONT (FIXME: Support stopping and continuing)
|
|
||||||
DefaultSignalAction::Terminate, // SIGPIPE
|
|
||||||
DefaultSignalAction::Terminate, // SIGALRM
|
|
||||||
DefaultSignalAction::Terminate, // SIGTERM
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void Thread::process_pending_signals(Registers* current_regs)
|
void Thread::process_pending_signals(Registers* current_regs)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < NSIG; i++)
|
for (int i = 0; i < NSIG; i++)
|
||||||
{
|
{
|
||||||
int signo = i + 1;
|
if (signal_mask & (1 << i)) continue;
|
||||||
if (signo != SIGKILL && signo != SIGSTOP && signal_mask & (1 << i)) continue;
|
|
||||||
if (pending_signals & (1 << i))
|
if (pending_signals & (1 << i))
|
||||||
{
|
{
|
||||||
|
int signo = i + 1;
|
||||||
pending_signals &= ~(1 << i);
|
pending_signals &= ~(1 << i);
|
||||||
kinfoln("signal: executing signal %d for thread %ld", signo, id);
|
kinfoln("signal: executing signal %d for thread %ld", signo, id);
|
||||||
auto handler = signal_handlers[i];
|
auto handler = signal_handlers[i];
|
||||||
if (signo != SIGKILL && signo != SIGSTOP && handler.sa_handler == SIG_IGN)
|
if (handler.sa_handler == SIG_IGN)
|
||||||
{
|
{
|
||||||
kinfoln("signal: ignoring signal (handler=SIG_IGN)");
|
kinfoln("signal: ignoring signal (handler=SIG_IGN)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (handler.sa_handler == SIG_DFL || signo == SIGKILL || signo == SIGSTOP)
|
if (handler.sa_handler == SIG_DFL)
|
||||||
{
|
{
|
||||||
default_signal:
|
default_signal:
|
||||||
if (id == 1)
|
if (id == 1)
|
||||||
|
@ -18,30 +18,9 @@ struct sigaction
|
|||||||
void* __sa_sigreturn = nullptr;
|
void* __sa_sigreturn = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constants for the 'how' parameter in sigprocmask().
|
|
||||||
#define SIG_BLOCK 0
|
|
||||||
#define SIG_UNBLOCK 1
|
|
||||||
#define SIG_SETMASK 2
|
|
||||||
|
|
||||||
// The signals with explicit numbers have portable signal numbers.
|
|
||||||
enum __signals
|
enum __signals
|
||||||
{
|
{
|
||||||
SIGHUP = 1,
|
SIGABRT = 1,
|
||||||
SIGINT = 2,
|
|
||||||
SIGQUIT = 3,
|
|
||||||
SIGILL = 4,
|
|
||||||
SIGTRAP = 5,
|
|
||||||
SIGABRT = 6,
|
|
||||||
SIGCHLD,
|
|
||||||
SIGFPE = 8,
|
|
||||||
SIGKILL = 9,
|
|
||||||
SIGSTOP,
|
|
||||||
SIGSEGV = 11,
|
|
||||||
SIGCONT,
|
|
||||||
SIGPIPE = 13,
|
|
||||||
SIGALRM = 14,
|
|
||||||
SIGTERM = 15,
|
|
||||||
// FIXME: Add the remaining signals.
|
|
||||||
__NSIG,
|
__NSIG,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,24 +25,6 @@ extern "C"
|
|||||||
/* Send a signal to the current thread. */
|
/* Send a signal to the current thread. */
|
||||||
int raise(int signo);
|
int raise(int signo);
|
||||||
|
|
||||||
/* Modify the current thread's signal mask. */
|
|
||||||
int sigprocmask(int how, const sigset_t* set, sigset_t* oldset);
|
|
||||||
|
|
||||||
/* Clear all signals from set. */
|
|
||||||
int sigemptyset(sigset_t* set);
|
|
||||||
|
|
||||||
/* Add all signals to set. */
|
|
||||||
int sigfillset(sigset_t* set);
|
|
||||||
|
|
||||||
/* Add a specific signal to set. */
|
|
||||||
int sigaddset(sigset_t* set, int signo);
|
|
||||||
|
|
||||||
/* Remove a specific signal from set. */
|
|
||||||
int sigdelset(sigset_t* set, int signo);
|
|
||||||
|
|
||||||
/* Check if a signal is in set.*/
|
|
||||||
int sigismember(const sigset_t* set, int signo);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,57 +23,4 @@ extern "C"
|
|||||||
{
|
{
|
||||||
return kill(getpid(), signo);
|
return kill(getpid(), signo);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sigprocmask(int how, const sigset_t* set, sigset_t* oldset)
|
|
||||||
{
|
|
||||||
long rc = syscall(SYS_sigprocmask, how, set, oldset);
|
|
||||||
__errno_return(rc, int);
|
|
||||||
}
|
|
||||||
|
|
||||||
int sigemptyset(sigset_t* set)
|
|
||||||
{
|
|
||||||
*set = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sigfillset(sigset_t* set)
|
|
||||||
{
|
|
||||||
*set = 0xffffffff;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sigaddset(sigset_t* set, int signo)
|
|
||||||
{
|
|
||||||
if (signo <= 0 || signo > NSIG)
|
|
||||||
{
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
*set |= (1 << (signo - 1));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sigdelset(sigset_t* set, int signo)
|
|
||||||
{
|
|
||||||
if (signo <= 0 || signo > NSIG)
|
|
||||||
{
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
*set &= ~(1 << (signo - 1));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sigismember(const sigset_t* set, int signo)
|
|
||||||
{
|
|
||||||
if (signo <= 0 || signo > NSIG)
|
|
||||||
{
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (*set & (1 << (signo - 1))) > 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
_e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(fchmodat) _e(fchownat) _e(ioctl) \
|
_e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(fchmodat) _e(fchownat) _e(ioctl) \
|
||||||
_e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \
|
_e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \
|
||||||
_e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) \
|
_e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) \
|
||||||
_e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill) _e(sigprocmask)
|
_e(pivot_root) _e(sigreturn) _e(sigaction) _e(kill)
|
||||||
|
|
||||||
enum Syscalls
|
enum Syscalls
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user