-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathsignal.c
111 lines (88 loc) · 2.4 KB
/
signal.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Copyright 2019 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Signal implementation.
#include <err.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include "debug.h"
// This is exported so the JS side can call us directly to deliver a signal.
//
// NB: The signal number uses musl ABI, not WASI ABI, and many signal numbers
// are different between the two!
void __wassh_signal_deliver(int signum) {
if (signum < 0 || signum >= NSIG)
return;
// There is no API to just read the current signal handler. So we have to set
// it to get the old value, use it, then restore it.
int old_errno = errno;
sighandler_t handler = signal(signum, SIG_IGN);
errno = old_errno;
if (handler == SIG_IGN)
return;
// Signals that have SIG_IGN as their default disposition don't register it as
// such initially. So we have to handle it ourselves.
if (handler == SIG_DFL &&
(signum == SIGCHLD || signum == SIGURG || signum == SIGWINCH)) {
goto done;
}
// SIG_ERR only happens with signals we can't catch.
if (handler == SIG_DFL || handler == SIG_ERR) {
errx(128 + signum, "Terminated by signal %i handler %p: %s", signum,
handler, strsignal(signum));
}
// Call the custom handler.
handler(signum);
done:
// Restore the handler.
signal(signum, handler);
}
#define sigmask(sig) (1 << ((sig) - 1))
int sigemptyset(sigset_t* set) {
if (set == NULL) {
errno = EINVAL;
return -1;
}
*set = 0;
return 0;
}
int sigfillset(sigset_t* set) {
if (set == NULL) {
errno = EINVAL;
return -1;
}
*set = -1;
return 0;
}
int sigaddset(sigset_t* set, int signum) {
if (set == NULL) {
errno = EINVAL;
return -1;
}
*set |= sigmask(signum);
return 0;
}
int sigdelset(sigset_t* set, int signum) {
if (set == NULL) {
errno = EINVAL;
return -1;
}
*set &= ~sigmask(signum);
return 0;
}
int sigismember(const sigset_t* set, int signum) {
if (set == NULL) {
errno = EINVAL;
return -1;
}
return *set | sigmask(signum);
}
int sigaction(int signum, const struct sigaction* act,
struct sigaction* oldact) {
if (oldact)
memset(oldact, 0, sizeof(*oldact));
if (act->sa_flags & SA_SIGINFO)
errx(1, "sigaction(%i): SA_SIGINFO not supported", signum);
return signal(signum, act->sa_handler) == SIG_ERR ? -1 : 0;
}