]> git.proxmox.com Git - wasi-libc.git/blob - libc-bottom-half/signal/signal.c
Fix typo
[wasi-libc.git] / libc-bottom-half / signal / signal.c
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
16 void __SIG_IGN(int sig) {
17 // do nothing
18 }
19
20 _Noreturn
21 void __SIG_ERR(int sig) {
22 __builtin_trap();
23 }
24
25 _Noreturn
26 static void core_handler(int sig) {
27 fprintf(stderr, "Program received fatal signal: %s\n", strsignal(sig));
28 abort();
29 }
30
31 _Noreturn
32 static void terminate_handler(int sig) {
33 fprintf(stderr, "Program recieved termination signal: %s\n", strsignal(sig));
34 abort();
35 }
36
37 _Noreturn
38 static void stop_handler(int sig) {
39 fprintf(stderr, "Program recieved stop signal: %s\n", strsignal(sig));
40 abort();
41 }
42
43 static void continue_handler(int sig) {
44 // do nothing
45 }
46
47 static 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
102 static sighandler_t handlers[_NSIG];
103
104 int 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
121 void (*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
141 extern __typeof(signal) bsd_signal __attribute__((weak, alias("signal")));
142 extern __typeof(signal) __sysv_signal __attribute__((weak, alias("signal")));