Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/wapython
Path: blob/main/core/kernel/src/wasm/posix/signal.ts
1068 views
1
/*
2
NOTES:
3
A key fact is that zig defines sigset_t to be "unsigned char", instead of a much
4
more useful larger struct. Thus we only have 8 bits, so can't really represent
5
all the signals. So instead we just use the pointer and a higher level Javascript
6
Set data structure. Since any nontrivial signal functionality has to be at the
7
Javascript level anyways, this is probably just fine.
8
9
They say this in the zig sources, and just worrying about the pointer makes things
10
agnostic.
11
12
// TODO: This is just a placeholder for now. Keep this in sync with musl.
13
typedef unsigned char sigset_t;
14
15
NOTE: below we implement more than just what's needed for Python. This may be helpful
16
for other libraries.
17
*/
18
19
import constants from "./constants";
20
import { notImplemented } from "./util";
21
22
const signal_t: { [setPtr: number]: Set<number> } = {};
23
24
export function getSignalSet(setPtr: number): Set<number> {
25
if (signal_t[setPtr] == null) {
26
signal_t[setPtr] = new Set();
27
}
28
return signal_t[setPtr];
29
}
30
31
export function setSignalSet(setPtr: number, value: Set<number>): void {
32
signal_t[setPtr] = value;
33
}
34
35
// The global signal mask for this process.
36
const signalMask = new Set<number>();
37
function setSignalSetToMask(setPtr: number): void {
38
const set = getSignalSet(setPtr);
39
set.clear();
40
for (const x of signalMask) {
41
set.add(x);
42
}
43
}
44
45
export default function signal({ process }) {
46
const signal = {
47
// int kill(pid_t pid, int sig);
48
kill: (pid: number, signal: number): number => {
49
if (process.kill == null) return 0;
50
process.kill(pid, signal);
51
return 0;
52
},
53
54
// NOTE: this is the single threaded version!
55
// int raise(int sig);
56
// according to man is same as "kill(getpid(), sig);" for single thread.
57
raise: (sig: number): number => {
58
return signal.kill(process.pid ?? 1, sig);
59
},
60
61
// int killpg(int pgrp, int sig);
62
killpg: (pid: number, signal: number): number => {
63
if (process.kill == null) return 0;
64
process.kill(-pid, signal);
65
return 0;
66
},
67
68
// int sigemptyset(sigset_t *set);
69
sigemptyset: (setPtr: number): number => {
70
getSignalSet(setPtr).clear();
71
return 0;
72
},
73
74
// int sigfillset(sigset_t *set);
75
sigfillset: (setPtr: number): number => {
76
const set = getSignalSet(setPtr);
77
for (let sig = 1; sig <= 31; sig++) {
78
set.add(sig);
79
}
80
return 0;
81
},
82
83
// int sigfillset(sigset_t *set);
84
85
// int sigaddset(sigset_t *set, int signum);
86
sigaddset: (setPtr: number, signum: number): number => {
87
getSignalSet(setPtr).add(signum);
88
return 0;
89
},
90
91
// int sigdelset(sigset_t *set, int signum);
92
sigdelset: (setPtr: number, signum: number): number => {
93
getSignalSet(setPtr).delete(signum);
94
return 0;
95
},
96
97
// int sigismember(const sigset_t *set, int signum);
98
sigismember: (setPtr: number, signum: number): number => {
99
if (getSignalSet(setPtr).has(signum)) {
100
return 1;
101
} else {
102
return 0;
103
}
104
},
105
106
// int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
107
// "sigprocmask() is used to fetch and/or change the signal mask of
108
// the calling thread. The signal mask is the set of signals whose
109
// delivery is currently blocked for the caller."
110
sigprocmask: (how: number, setPtr: number, oldsetPtr: number): number => {
111
try {
112
if (!setPtr) return 0;
113
const set = getSignalSet(setPtr);
114
switch (how) {
115
case constants.SIG_BLOCK:
116
for (const s of set) {
117
signalMask.add(s);
118
}
119
return 0;
120
case constants.SIG_UNBLOCK:
121
for (const s of set) {
122
signalMask.delete(s);
123
}
124
return 0;
125
case constants.SIG_SETMASK:
126
signalMask.clear();
127
for (const s of set) {
128
signalMask.add(s);
129
}
130
return 0;
131
default:
132
throw Error(`sigprocmask - invalid how=${how}`);
133
}
134
} finally {
135
if (oldsetPtr) {
136
setSignalSetToMask(oldsetPtr);
137
}
138
}
139
},
140
141
// int sigsuspend(const sigset_t *sigmask);
142
sigsuspend: () => {
143
notImplemented("sigsuspend");
144
},
145
};
146
147
// for single threaded programs, these are the same:
148
// @ts-ignore
149
signal.pthread_sigmask = signal.sigprocmask;
150
151
return signal;
152
}
153
154