1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2 * Permission is hereby granted, free of charge, to any person obtaining a copy
3 * of this software and associated documentation files (the "Software"), to
4 * deal in the Software without restriction, including without limitation the
5 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6 * sell copies of the Software, and to permit persons to whom the Software is
7 * furnished to do so, subject to the following conditions:
9 * The above copyright notice and this permission notice shall be included in
10 * all copies or substantial portions of the Software.
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
37 RB_HEAD(uv__signal_tree_s, uv_signal_s);
40 static int uv__signal_unlock();
41 static void uv__signal_event(uv_loop_t* loop, uv__io_t* w, unsigned int events);
42 static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2);
43 static void uv__signal_stop(uv_signal_t* handle);
46 static pthread_once_t uv__signal_global_init_guard = PTHREAD_ONCE_INIT;
47 static struct uv__signal_tree_s uv__signal_tree =
48 RB_INITIALIZER(uv__signal_tree);
49 static int uv__signal_lock_pipefd[2];
52 RB_GENERATE_STATIC(uv__signal_tree_s,
53 uv_signal_s, tree_entry,
57 static void uv__signal_global_init(void) {
58 if (uv__make_pipe(uv__signal_lock_pipefd, 0))
61 if (uv__signal_unlock())
66 void uv__signal_global_once_init(void) {
67 pthread_once(&uv__signal_global_init_guard, uv__signal_global_init);
72 static int uv__signal_lock(void) {
77 r = read(uv__signal_lock_pipefd[0], &data, sizeof data);
78 } while (r < 0 && errno == EINTR);
80 return (r < 0) ? -1 : 0;
84 static int uv__signal_unlock(void) {
89 r = write(uv__signal_lock_pipefd[1], &data, sizeof data);
90 } while (r < 0 && errno == EINTR);
92 return (r < 0) ? -1 : 0;
96 static void uv__signal_block_and_lock(sigset_t* saved_sigmask) {
99 if (sigfillset(&new_mask))
102 if (pthread_sigmask(SIG_SETMASK, &new_mask, saved_sigmask))
105 if (uv__signal_lock())
110 static void uv__signal_unlock_and_unblock(sigset_t* saved_sigmask) {
111 if (uv__signal_unlock())
114 if (pthread_sigmask(SIG_SETMASK, saved_sigmask, NULL))
119 inline static uv_signal_t* uv__signal_first_handle(int signum) {
120 /* This function must be called with the signal lock held. */
124 lookup.signum = signum;
127 handle = RB_NFIND(uv__signal_tree_s, &uv__signal_tree, &lookup);
129 if (handle != NULL && handle->signum == signum)
136 static void uv__signal_handler(int signum) {
137 uv__signal_msg_t msg;
142 memset(&msg, 0, sizeof msg);
144 if (uv__signal_lock()) {
149 for (handle = uv__signal_first_handle(signum);
150 handle != NULL && handle->signum == signum;
151 handle = RB_NEXT(uv__signal_tree_s, &uv__signal_tree, handle)) {
157 /* write() should be atomic for small data chunks, so the entire message
158 * should be written at once. In theory the pipe could become full, in
159 * which case the user is out of luck.
162 r = write(handle->loop->signal_pipefd[1], &msg, sizeof msg);
163 } while (r == -1 && errno == EINTR);
165 assert(r == sizeof msg ||
166 (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)));
169 handle->caught_signals++;
177 static uv_err_t uv__signal_register_handler(int signum) {
178 /* When this function is called, the signal lock must be held. */
181 /* XXX use a separate signal stack? */
182 memset(&sa, 0, sizeof(sa));
183 if (sigfillset(&sa.sa_mask))
185 sa.sa_handler = uv__signal_handler;
187 /* XXX save old action so we can restore it later on? */
188 if (sigaction(signum, &sa, NULL))
189 return uv__new_sys_error(errno);
195 static void uv__signal_unregister_handler(int signum) {
196 /* When this function is called, the signal lock must be held. */
199 memset(&sa, 0, sizeof(sa));
200 sa.sa_handler = SIG_DFL;
202 /* sigaction can only fail with EINVAL or EFAULT; an attempt to deregister a
203 * signal implies that it was successfully registered earlier, so EINVAL
204 * should never happen.
206 if (sigaction(signum, &sa, NULL))
211 static int uv__signal_loop_once_init(uv_loop_t* loop) {
212 /* Return if already initialized. */
213 if (loop->signal_pipefd[0] != -1)
216 if (uv__make_pipe(loop->signal_pipefd, UV__F_NONBLOCK))
219 uv__io_init(&loop->signal_io_watcher,
221 loop->signal_pipefd[0]);
222 uv__io_start(loop, &loop->signal_io_watcher, UV__POLLIN);
228 void uv__signal_loop_cleanup(uv_loop_t* loop) {
231 /* Stop all the signal watchers that are still attached to this loop. This
232 * ensures that the (shared) signal tree doesn't contain any invalid entries
233 * entries, and that signal handlers are removed when appropriate.
235 ngx_queue_foreach(q, &loop->handle_queue) {
236 uv_handle_t* handle = ngx_queue_data(q, uv_handle_t, handle_queue);
238 if (handle->type == UV_SIGNAL)
239 uv__signal_stop((uv_signal_t*) handle);
242 if (loop->signal_pipefd[0] != -1) {
243 close(loop->signal_pipefd[0]);
244 loop->signal_pipefd[0] = -1;
247 if (loop->signal_pipefd[1] != -1) {
248 close(loop->signal_pipefd[1]);
249 loop->signal_pipefd[1] = -1;
254 int uv_signal_init(uv_loop_t* loop, uv_signal_t* handle) {
255 if (uv__signal_loop_once_init(loop))
256 return uv__set_sys_error(loop, errno);
258 uv__handle_init(loop, (uv_handle_t*) handle, UV_SIGNAL);
260 handle->caught_signals = 0;
261 handle->dispatched_signals = 0;
267 void uv__signal_close(uv_signal_t* handle) {
269 uv__signal_stop(handle);
271 /* If there are any caught signals "trapped" in the signal pipe, we can't
272 * call the close callback yet. Otherwise, add the handle to the finish_close
275 if (handle->caught_signals == handle->dispatched_signals) {
276 uv__make_close_pending((uv_handle_t*) handle);
281 int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) {
282 sigset_t saved_sigmask;
284 assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
286 /* If the user supplies signum == 0, then return an error already. If the
287 * signum is otherwise invalid then uv__signal_register will find out
291 uv__set_artificial_error(handle->loop, UV_EINVAL);
295 /* Short circuit: if the signal watcher is already watching {signum} don't
296 * go through the process of deregistering and registering the handler.
297 * Additionally, this avoids pending signals getting lost in the small time
298 * time frame that handle->signum == 0.
300 if (signum == handle->signum) {
301 handle->signal_cb = signal_cb;
305 /* If the signal handler was already active, stop it first. */
306 if (handle->signum != 0) {
307 uv__signal_stop(handle);
310 uv__signal_block_and_lock(&saved_sigmask);
312 /* If at this point there are no active signal watchers for this signum (in
313 * any of the loops), it's time to try and register a handler for it here.
315 if (uv__signal_first_handle(signum) == NULL) {
316 uv_err_t err = uv__signal_register_handler(signum);
317 if (err.code != UV_OK) {
318 /* Registering the signal handler failed. Must be an invalid signal. */
319 handle->loop->last_err = err;
320 uv__signal_unlock_and_unblock(&saved_sigmask);
325 handle->signum = signum;
326 RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle);
328 uv__signal_unlock_and_unblock(&saved_sigmask);
330 handle->signal_cb = signal_cb;
331 uv__handle_start(handle);
337 static void uv__signal_event(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
338 uv__signal_msg_t* msg;
340 char buf[sizeof(uv__signal_msg_t) * 32];
341 size_t bytes, end, i;
347 r = read(loop->signal_pipefd[0], buf + bytes, sizeof(buf) - bytes);
349 if (r == -1 && errno == EINTR)
352 if (r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
353 /* If there are bytes in the buffer already (which really is extremely
354 * unlikely if possible at all) we can't exit the function here. We'll
355 * spin until more bytes are read instead.
360 /* Otherwise, there was nothing there. */
364 /* Other errors really should never happen. */
370 /* `end` is rounded down to a multiple of sizeof(uv__signal_msg_t). */
371 end = (bytes / sizeof(uv__signal_msg_t)) * sizeof(uv__signal_msg_t);
373 for (i = 0; i < end; i += sizeof(uv__signal_msg_t)) {
374 msg = (uv__signal_msg_t*) (buf + i);
375 handle = msg->handle;
377 if (msg->signum == handle->signum) {
378 assert(!(handle->flags & UV_CLOSING));
379 handle->signal_cb(handle, handle->signum);
382 handle->dispatched_signals++;
384 /* If uv_close was called while there were caught signals that were not
385 * yet dispatched, the uv__finish_close was deferred. Make close pending
386 * now if this has happened.
388 if ((handle->flags & UV_CLOSING) &&
389 (handle->caught_signals == handle->dispatched_signals)) {
390 uv__make_close_pending((uv_handle_t*) handle);
396 /* If there are any "partial" messages left, move them to the start of the
397 * the buffer, and spin. This should not happen.
400 memmove(buf, buf + end, bytes);
403 } while (end == sizeof buf);
407 static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) {
408 /* Compare signums first so all watchers with the same signnum end up
411 if (w1->signum < w2->signum) return -1;
412 if (w1->signum > w2->signum) return 1;
414 /* Sort by loop pointer, so we can easily look up the first item after
415 * { .signum = x, .loop = NULL }.
417 if (w1->loop < w2->loop) return -1;
418 if (w1->loop > w2->loop) return 1;
420 if (w1 < w2) return -1;
421 if (w1 > w2) return 1;
427 int uv_signal_stop(uv_signal_t* handle) {
428 assert(!(handle->flags & (UV_CLOSING | UV_CLOSED)));
429 uv__signal_stop(handle);
434 static void uv__signal_stop(uv_signal_t* handle) {
435 uv_signal_t* removed_handle;
436 sigset_t saved_sigmask;
438 /* If the watcher wasn't started, this is a no-op. */
439 if (handle->signum == 0)
442 uv__signal_block_and_lock(&saved_sigmask);
444 removed_handle = RB_REMOVE(uv__signal_tree_s, &uv__signal_tree, handle);
445 assert(removed_handle == handle);
446 (void) removed_handle;
448 /* Check if there are other active signal watchers observing this signal. If
449 * not, unregister the signal handler.
451 if (uv__signal_first_handle(handle->signum) == NULL)
452 uv__signal_unregister_handler(handle->signum);
454 uv__signal_unlock_and_unblock(&saved_sigmask);
457 uv__handle_stop(handle);