master
1// Userspace emulation of `raise` and `signal`.
2//
3// WebAssembly doesn't support asynchronous signal delivery, so we can't
4// support it in WASI libc. But we can make things like `raise` work.
5
6#define _WASI_EMULATED_SIGNAL
7#define _ALL_SOURCE
8#define _GNU_SOURCE
9#include <signal.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <errno.h>
13#include <string.h>
14#include <assert.h>
15
16void __SIG_IGN(int sig) {
17 // do nothing
18}
19
20_Noreturn
21void __SIG_ERR(int sig) {
22 __builtin_trap();
23}
24
25_Noreturn
26static void core_handler(int sig) {
27 fprintf(stderr, "Program received fatal signal: %s\n", strsignal(sig));
28 abort();
29}
30
31_Noreturn
32static void terminate_handler(int sig) {
33 fprintf(stderr, "Program received termination signal: %s\n", strsignal(sig));
34 abort();
35}
36
37_Noreturn
38static void stop_handler(int sig) {
39 fprintf(stderr, "Program received stop signal: %s\n", strsignal(sig));
40 abort();
41}
42
43static void continue_handler(int sig) {
44 // do nothing
45}
46
47static const sighandler_t default_handlers[_NSIG] = {
48 // Default behavior: "core".
49 [SIGABRT] = core_handler,
50 [SIGBUS] = core_handler,
51 [SIGFPE] = core_handler,
52 [SIGILL] = core_handler,
53#if SIGIOT != SIGABRT
54 [SIGIOT] = core_handler,
55#endif
56 [SIGQUIT] = core_handler,
57 [SIGSEGV] = core_handler,
58 [SIGSYS] = core_handler,
59 [SIGTRAP] = core_handler,
60 [SIGXCPU] = core_handler,
61 [SIGXFSZ] = core_handler,
62#if defined(SIGUNUSED) && SIGUNUSED != SIGSYS
63 [SIGUNUSED] = core_handler,
64#endif
65
66 // Default behavior: ignore.
67 [SIGCHLD] = SIG_IGN,
68#if defined(SIGCLD) && SIGCLD != SIGCHLD
69 [SIGCLD] = SIG_IGN,
70#endif
71 [SIGURG] = SIG_IGN,
72 [SIGWINCH] = SIG_IGN,
73
74 // Default behavior: "continue".
75 [SIGCONT] = continue_handler,
76
77 // Default behavior: "stop".
78 [SIGSTOP] = stop_handler,
79 [SIGTSTP] = stop_handler,
80 [SIGTTIN] = stop_handler,
81 [SIGTTOU] = stop_handler,
82
83 // Default behavior: "terminate".
84 [SIGHUP] = terminate_handler,
85 [SIGINT] = terminate_handler,
86 [SIGKILL] = terminate_handler,
87 [SIGUSR1] = terminate_handler,
88 [SIGUSR2] = terminate_handler,
89 [SIGPIPE] = terminate_handler,
90 [SIGALRM] = terminate_handler,
91 [SIGTERM] = terminate_handler,
92 [SIGSTKFLT] = terminate_handler,
93 [SIGVTALRM] = terminate_handler,
94 [SIGPROF] = terminate_handler,
95 [SIGIO] = terminate_handler,
96#if SIGPOLL != SIGIO
97 [SIGPOLL] = terminate_handler,
98#endif
99 [SIGPWR] = terminate_handler,
100};
101
102static sighandler_t handlers[_NSIG];
103
104int raise(int sig) {
105 if (sig < 0 || sig >= _NSIG) {
106 errno = EINVAL;
107 return -1;
108 }
109
110 sighandler_t func = handlers[sig];
111
112 if (func == NULL) {
113 default_handlers[sig](sig);
114 } else {
115 func(sig);
116 }
117
118 return 0;
119}
120
121void (*signal(int sig, void (*func)(int)))(int) {
122 assert(SIG_DFL == NULL);
123
124 if (sig < 0 || sig >= _NSIG) {
125 errno = EINVAL;
126 return SIG_ERR;
127 }
128
129 if (sig == SIGKILL || sig == SIGSTOP) {
130 errno = EINVAL;
131 return SIG_ERR;
132 }
133
134 sighandler_t old = handlers[sig];
135
136 handlers[sig] = func;
137
138 return old;
139}
140
141extern __typeof(signal) bsd_signal __attribute__((weak, alias("signal")));
142extern __typeof(signal) __sysv_signal __attribute__((weak, alias("signal")));