Path: blob/main/core/kernel/src/wasm/posix/signal.ts
1068 views
/*1NOTES:2A key fact is that zig defines sigset_t to be "unsigned char", instead of a much3more useful larger struct. Thus we only have 8 bits, so can't really represent4all the signals. So instead we just use the pointer and a higher level Javascript5Set data structure. Since any nontrivial signal functionality has to be at the6Javascript level anyways, this is probably just fine.78They say this in the zig sources, and just worrying about the pointer makes things9agnostic.1011// TODO: This is just a placeholder for now. Keep this in sync with musl.12typedef unsigned char sigset_t;1314NOTE: below we implement more than just what's needed for Python. This may be helpful15for other libraries.16*/1718import constants from "./constants";19import { notImplemented } from "./util";2021const signal_t: { [setPtr: number]: Set<number> } = {};2223export function getSignalSet(setPtr: number): Set<number> {24if (signal_t[setPtr] == null) {25signal_t[setPtr] = new Set();26}27return signal_t[setPtr];28}2930export function setSignalSet(setPtr: number, value: Set<number>): void {31signal_t[setPtr] = value;32}3334// The global signal mask for this process.35const signalMask = new Set<number>();36function setSignalSetToMask(setPtr: number): void {37const set = getSignalSet(setPtr);38set.clear();39for (const x of signalMask) {40set.add(x);41}42}4344export default function signal({ process }) {45const signal = {46// int kill(pid_t pid, int sig);47kill: (pid: number, signal: number): number => {48if (process.kill == null) return 0;49process.kill(pid, signal);50return 0;51},5253// NOTE: this is the single threaded version!54// int raise(int sig);55// according to man is same as "kill(getpid(), sig);" for single thread.56raise: (sig: number): number => {57return signal.kill(process.pid ?? 1, sig);58},5960// int killpg(int pgrp, int sig);61killpg: (pid: number, signal: number): number => {62if (process.kill == null) return 0;63process.kill(-pid, signal);64return 0;65},6667// int sigemptyset(sigset_t *set);68sigemptyset: (setPtr: number): number => {69getSignalSet(setPtr).clear();70return 0;71},7273// int sigfillset(sigset_t *set);74sigfillset: (setPtr: number): number => {75const set = getSignalSet(setPtr);76for (let sig = 1; sig <= 31; sig++) {77set.add(sig);78}79return 0;80},8182// int sigfillset(sigset_t *set);8384// int sigaddset(sigset_t *set, int signum);85sigaddset: (setPtr: number, signum: number): number => {86getSignalSet(setPtr).add(signum);87return 0;88},8990// int sigdelset(sigset_t *set, int signum);91sigdelset: (setPtr: number, signum: number): number => {92getSignalSet(setPtr).delete(signum);93return 0;94},9596// int sigismember(const sigset_t *set, int signum);97sigismember: (setPtr: number, signum: number): number => {98if (getSignalSet(setPtr).has(signum)) {99return 1;100} else {101return 0;102}103},104105// int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);106// "sigprocmask() is used to fetch and/or change the signal mask of107// the calling thread. The signal mask is the set of signals whose108// delivery is currently blocked for the caller."109sigprocmask: (how: number, setPtr: number, oldsetPtr: number): number => {110try {111if (!setPtr) return 0;112const set = getSignalSet(setPtr);113switch (how) {114case constants.SIG_BLOCK:115for (const s of set) {116signalMask.add(s);117}118return 0;119case constants.SIG_UNBLOCK:120for (const s of set) {121signalMask.delete(s);122}123return 0;124case constants.SIG_SETMASK:125signalMask.clear();126for (const s of set) {127signalMask.add(s);128}129return 0;130default:131throw Error(`sigprocmask - invalid how=${how}`);132}133} finally {134if (oldsetPtr) {135setSignalSetToMask(oldsetPtr);136}137}138},139140// int sigsuspend(const sigset_t *sigmask);141sigsuspend: () => {142notImplemented("sigsuspend");143},144};145146// for single threaded programs, these are the same:147// @ts-ignore148signal.pthread_sigmask = signal.sigprocmask;149150return signal;151}152153154