/home/travis/build/MoarVM/MoarVM/src/io/signals.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "moar.h" |
2 | | |
3 | | #include <signal.h> |
4 | | #ifdef _WIN32 |
5 | | #define SIGHUP 1 |
6 | | #define SIGKILL 9 |
7 | | #define SIGWINCH 28 |
8 | | #endif |
9 | | |
10 | | /* Info we convey about a signal handler. */ |
11 | | typedef struct { |
12 | | int signum; |
13 | | uv_signal_t handle; |
14 | | MVMThreadContext *tc; |
15 | | int work_idx; |
16 | | } SignalInfo; |
17 | | |
18 | | /* Signal callback; dispatches schedulee to the queue. */ |
19 | 0 | static void signal_cb(uv_signal_t *handle, int sig_num) { |
20 | 0 | SignalInfo *si = (SignalInfo *)handle->data; |
21 | 0 | MVMThreadContext *tc = si->tc; |
22 | 0 | MVMObject *arr = MVM_repr_alloc_init(tc, tc->instance->boot_types.BOOTArray); |
23 | 0 | MVMAsyncTask *t = MVM_io_eventloop_get_active_work(tc, si->work_idx); |
24 | 0 | MVM_repr_push_o(tc, arr, t->body.schedulee); |
25 | 0 | MVMROOT(tc, t, { |
26 | 0 | MVMROOT(tc, arr, { |
27 | 0 | MVMObject *sig_num_boxed = MVM_repr_box_int(tc, |
28 | 0 | tc->instance->boot_types.BOOTInt, sig_num); |
29 | 0 | MVM_repr_push_o(tc, arr, sig_num_boxed); |
30 | 0 | }); |
31 | 0 | }); |
32 | 0 | MVM_repr_push_o(tc, t->body.queue, arr); |
33 | 0 | } |
34 | | |
35 | | /* Sets the signal handler up on the event loop. */ |
36 | 0 | static void setup(MVMThreadContext *tc, uv_loop_t *loop, MVMObject *async_task, void *data) { |
37 | 0 | SignalInfo *si = (SignalInfo *)data; |
38 | 0 | uv_signal_init(loop, &si->handle); |
39 | 0 | si->work_idx = MVM_io_eventloop_add_active_work(tc, async_task); |
40 | 0 | si->tc = tc; |
41 | 0 | si->handle.data = si; |
42 | 0 | uv_signal_start(&si->handle, signal_cb, si->signum); |
43 | 0 | } |
44 | | |
45 | | /* Frees data associated with a timer async task. */ |
46 | 0 | static void gc_free(MVMThreadContext *tc, MVMObject *t, void *data) { |
47 | 0 | if (data) |
48 | 0 | MVM_free(data); |
49 | 0 | } |
50 | | |
51 | | /* Operations table for async timer task. */ |
52 | | static const MVMAsyncTaskOps op_table = { |
53 | | setup, |
54 | | NULL, |
55 | | NULL, |
56 | | gc_free |
57 | | }; |
58 | | |
59 | | /* Creates a new timer. */ |
60 | | MVMObject * MVM_io_signal_handle(MVMThreadContext *tc, MVMObject *queue, |
61 | | MVMObject *schedulee, MVMint64 signal, |
62 | 0 | MVMObject *async_type) { |
63 | 0 | MVMAsyncTask *task; |
64 | 0 | SignalInfo *signal_info; |
65 | 0 | int signum; |
66 | 0 |
|
67 | 0 | /* Transform the signal number. */ |
68 | 0 | switch (signal) { |
69 | 0 | case MVM_SIG_HUP: signum = SIGHUP; break; |
70 | 0 | case MVM_SIG_INT: signum = SIGINT; break; |
71 | 0 | #ifdef SIGQUIT |
72 | 0 | case MVM_SIG_QUIT: signum = SIGQUIT; break; |
73 | 0 | #endif |
74 | 0 | #ifdef SIGILL |
75 | 0 | case MVM_SIG_ILL: signum = SIGILL; break; |
76 | 0 | #endif |
77 | 0 | #ifdef SIGTRAP |
78 | 0 | case MVM_SIG_TRAP: signum = SIGTRAP; break; |
79 | 0 | #endif |
80 | 0 | #ifdef SIGABRT |
81 | 0 | case MVM_SIG_ABRT: signum = SIGABRT; break; |
82 | 0 | #endif |
83 | 0 | #ifdef SIGEMT |
84 | | case MVM_SIG_EMT: signum = SIGEMT; break; |
85 | | #endif |
86 | 0 | #ifdef SIGFPE |
87 | 0 | case MVM_SIG_FPE: signum = SIGFPE; break; |
88 | 0 | #endif |
89 | 0 | #ifdef SIGKILL |
90 | 0 | case MVM_SIG_KILL: signum = SIGKILL; break; |
91 | 0 | #endif |
92 | 0 | #ifdef SIGBUS |
93 | 0 | case MVM_SIG_BUS: signum = SIGBUS; break; |
94 | 0 | #endif |
95 | 0 | #ifdef SIGSEGV |
96 | 0 | case MVM_SIG_SEGV: signum = SIGSEGV; break; |
97 | 0 | #endif |
98 | 0 | #ifdef SIGSYS |
99 | 0 | case MVM_SIG_SYS: signum = SIGSYS; break; |
100 | 0 | #endif |
101 | 0 | #ifdef SIGPIPE |
102 | 0 | case MVM_SIG_PIPE: signum = SIGPIPE; break; |
103 | 0 | #endif |
104 | 0 | #ifdef SIGALRM |
105 | 0 | case MVM_SIG_ALRM: signum = SIGALRM; break; |
106 | 0 | #endif |
107 | 0 | #ifdef SIGTERM |
108 | 0 | case MVM_SIG_TERM: signum = SIGTERM; break; |
109 | 0 | #endif |
110 | 0 | #ifdef SIGURG |
111 | 0 | case MVM_SIG_URG: signum = SIGURG; break; |
112 | 0 | #endif |
113 | 0 | #ifdef SIGSTOP |
114 | 0 | case MVM_SIG_STOP: signum = SIGSTOP; break; /* hammer time */ |
115 | 0 | #endif |
116 | 0 | #ifdef SIGTSTP |
117 | 0 | case MVM_SIG_TSTP: signum = SIGTSTP; break; |
118 | 0 | #endif |
119 | 0 | #ifdef SIGCONT |
120 | 0 | case MVM_SIG_CONT: signum = SIGCONT; break; |
121 | 0 | #endif |
122 | 0 | #ifdef SIGCHLD |
123 | 0 | case MVM_SIG_CHLD: signum = SIGCHLD; break; |
124 | 0 | #endif |
125 | 0 | #ifdef SIGTTIN |
126 | 0 | case MVM_SIG_TTIN: signum = SIGTTIN; break; |
127 | 0 | #endif |
128 | 0 | #ifdef SIGTTOU |
129 | 0 | case MVM_SIG_TTOU: signum = SIGTTOU; break; |
130 | 0 | #endif |
131 | 0 | #ifdef SIGIO |
132 | 0 | case MVM_SIG_IO: signum = SIGIO; break; |
133 | 0 | #endif |
134 | 0 | #ifdef SIGXCPU |
135 | 0 | case MVM_SIG_XCPU: signum = SIGXCPU; break; |
136 | 0 | #endif |
137 | 0 | #ifdef SIGXFSZ |
138 | 0 | case MVM_SIG_XFSZ: signum = SIGXFSZ; break; |
139 | 0 | #endif |
140 | 0 | #ifdef SIGVTALRM |
141 | 0 | case MVM_SIG_VTALRM: signum = SIGVTALRM; break; |
142 | 0 | #endif |
143 | 0 | #ifdef SIGPROF |
144 | 0 | case MVM_SIG_PROF: signum = SIGPROF; break; |
145 | 0 | #endif |
146 | 0 | #ifdef SIGWINCH |
147 | 0 | case MVM_SIG_WINCH: signum = SIGWINCH; break; |
148 | 0 | #endif |
149 | 0 | #ifdef SIGINFO |
150 | | case MVM_SIG_INFO: signum = SIGINFO; break; |
151 | | #endif |
152 | 0 | #ifdef SIGUSR1 |
153 | 0 | case MVM_SIG_USR1: signum = SIGUSR1; break; |
154 | 0 | #endif |
155 | 0 | #ifdef SIGUSR2 |
156 | 0 | case MVM_SIG_USR2: signum = SIGUSR2; break; |
157 | 0 | #endif |
158 | 0 | #ifdef SIGTHR |
159 | | case MVM_SIG_THR: signum = SIGTHR; break; |
160 | | #endif |
161 | 0 | #ifdef SIGSTKFLT |
162 | 0 | case MVM_SIG_STKFLT: signum = SIGSTKFLT; break; |
163 | 0 | #endif |
164 | 0 | #ifdef SIGPWR |
165 | 0 | case MVM_SIG_PWR: signum = SIGPWR; break; |
166 | 0 | #endif |
167 | 0 | #ifdef SIGBREAK |
168 | | case MVM_SIG_BREAK: signum = SIGBREAK; break; |
169 | | #endif |
170 | 0 | default: |
171 | 0 | MVM_exception_throw_adhoc(tc, "Unsupported signal handler %d", |
172 | 0 | (int)signal); |
173 | 0 | } |
174 | 0 |
|
175 | 0 | /* Validate REPRs. */ |
176 | 0 | if (REPR(queue)->ID != MVM_REPR_ID_ConcBlockingQueue) |
177 | 0 | MVM_exception_throw_adhoc(tc, |
178 | 0 | "signal target queue must have ConcBlockingQueue REPR"); |
179 | 0 | if (REPR(async_type)->ID != MVM_REPR_ID_MVMAsyncTask) |
180 | 0 | MVM_exception_throw_adhoc(tc, |
181 | 0 | "signal result type must have REPR AsyncTask"); |
182 | 0 |
|
183 | 0 | /* Create async task handle. */ |
184 | 0 | MVMROOT(tc, queue, { |
185 | 0 | MVMROOT(tc, schedulee, { |
186 | 0 | task = (MVMAsyncTask *)MVM_repr_alloc_init(tc, async_type); |
187 | 0 | }); |
188 | 0 | }); |
189 | 0 | MVM_ASSIGN_REF(tc, &(task->common.header), task->body.queue, queue); |
190 | 0 | MVM_ASSIGN_REF(tc, &(task->common.header), task->body.schedulee, schedulee); |
191 | 0 | task->body.ops = &op_table; |
192 | 0 | signal_info = MVM_malloc(sizeof(SignalInfo)); |
193 | 0 | signal_info->signum = signum; |
194 | 0 | task->body.data = signal_info; |
195 | 0 |
|
196 | 0 | /* Hand the task off to the event loop. */ |
197 | 0 | MVMROOT(tc, task, { |
198 | 0 | MVM_io_eventloop_queue_work(tc, (MVMObject *)task); |
199 | 0 | }); |
200 | 0 |
|
201 | 0 | return (MVMObject *)task; |
202 | 0 | } |