Coverage Report

Created: 2017-04-15 07:07

/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
}