Orion
Barry Moving signal handlers into separate namespace 7ae31b0 (2 years, 4 months ago)/* * This file handles signals to tasks. It handles blocking signals, and * registering the signal handlers. It send/dispatches signals to tasks and * runs the registered signal handlers when appropriate. */ #include <stdint.h> #include <errno.h> #include "task.h" extern TaskQueue tasks; /* Handle the signals for a task */ void handle_signals(void) { if (!(current->sigset & ~current->blockedSignals)) return; int signal; for (signal = 0; signal < 32; signal++) { if (!(current->sigset & (1 << (signal - 1)))) continue; current->status = signal; terminate(); } } /* Send a signal to a task */ void send_sig(Task *target, int sig) { target->sigset |= (1 << (sig - 1)); } /* Send a signal to a thread */ int tgkill(pid_t tgid, pid_t tid, int sig) { if (sig < 0 || sig >= 32) return -EINVAL; Task *task = find_task(tid); if (!task || task->tgid != tgid) return -ESRCH; if (sig) send_sig(task, sig); return 0; } /* Send a signal to a process */ int kill(pid_t pid, int sig) { if (sig < 0 || sig >= 32) return -EINVAL; int sent = 0; Task *task; for (task = tasks.start; task; task = task->tnext) { if (task->tgid != pid) continue; if (sig) send_sig(task, sig); sent++; } return sent ? 0 : -ESRCH; } /* Install a signal handler */ sighandler_t signal(int signum, sighandler_t handler) { if (signum < 0 || signum >= 32) return (sighandler_t) -EINVAL; if (!verify_access(handler, 8, PROT_EXEC)) return (sighandler_t) -EFAULT; sighandler_t old = current->signals->sig_handler[signum]; current->signals->sig_handler[signum] = handler; return old; } /* Examine and change blocked signals */ int sigprocmask(int how, const sigset_t *set, sigset_t *oldset) { if (!verify_access(set, sizeof(sigset_t), PROT_READ)) return -EFAULT; if (!verify_access(oldset, sizeof(sigset_t), PROT_WRITE)) return -EFAULT; if (oldset) *oldset = current->blockedSignals; if (!set) return 0; switch (how) { case SIG_BLOCK: current->blockedSignals |= *set; return 0; case SIG_UNBLOCK: current->blockedSignals &= ~*set; return 0; case SIG_SETMASK: current->blockedSignals = *set; return 0; default: return -EINVAL; } }