]> granicus.if.org Git - libevent/blob - signal.c
buffer: use pread() for evbuffer_file_segment_materialize()
[libevent] / signal.c
1 /*      $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $       */
2
3 /*
4  * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu>
5  * Copyright 2007-2012 Niels Provos and Nick Mathewson
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 #include "event2/event-config.h"
30 #include "evconfig-private.h"
31
32 #ifdef _WIN32
33 #define WIN32_LEAN_AND_MEAN
34 #include <winsock2.h>
35 #include <windows.h>
36 #undef WIN32_LEAN_AND_MEAN
37 #endif
38 #include <sys/types.h>
39 #ifdef EVENT__HAVE_SYS_TIME_H
40 #include <sys/time.h>
41 #endif
42 #include <sys/queue.h>
43 #ifdef EVENT__HAVE_SYS_SOCKET_H
44 #include <sys/socket.h>
45 #endif
46 #include <signal.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #ifdef EVENT__HAVE_UNISTD_H
51 #include <unistd.h>
52 #endif
53 #include <errno.h>
54 #ifdef EVENT__HAVE_FCNTL_H
55 #include <fcntl.h>
56 #endif
57
58 #include "event2/event.h"
59 #include "event2/event_struct.h"
60 #include "event-internal.h"
61 #include "event2/util.h"
62 #include "evsignal-internal.h"
63 #include "log-internal.h"
64 #include "evmap-internal.h"
65 #include "evthread-internal.h"
66
67 /*
68   signal.c
69
70   This is the signal-handling implementation we use for backends that don't
71   have a better way to do signal handling.  It uses sigaction() or signal()
72   to set a signal handler, and a socket pair to tell the event base when
73
74   Note that I said "the event base" : only one event base can be set up to use
75   this at a time.  For historical reasons and backward compatibility, if you
76   add an event for a signal to event_base A, then add an event for a signal
77   (any signal!) to event_base B, event_base B will get informed about the
78   signal, but event_base A won't.
79
80   It would be neat to change this behavior in some future version of Libevent.
81   kqueue already does something far more sensible.  We can make all backends
82   on Linux do a reasonable thing using signalfd.
83 */
84
85 #ifndef _WIN32
86 /* Windows wants us to call our signal handlers as __cdecl.  Nobody else
87  * expects you to do anything crazy like this. */
88 #ifndef __cdecl
89 #define __cdecl
90 #endif
91 #endif
92
93 static int evsig_add(struct event_base *, evutil_socket_t, short, short, void *);
94 static int evsig_del(struct event_base *, evutil_socket_t, short, short, void *);
95
96 static const struct eventop evsigops = {
97         "signal",
98         NULL,
99         evsig_add,
100         evsig_del,
101         NULL,
102         NULL,
103         0, 0, 0
104 };
105
106 #ifndef EVENT__DISABLE_THREAD_SUPPORT
107 /* Lock for evsig_base and evsig_base_n_signals_added fields. */
108 static void *evsig_base_lock = NULL;
109 #endif
110 /* The event base that's currently getting informed about signals. */
111 static struct event_base *evsig_base = NULL;
112 /* A copy of evsig_base->sigev_n_signals_added. */
113 static int evsig_base_n_signals_added = 0;
114 static evutil_socket_t evsig_base_fd = -1;
115
116 static void __cdecl evsig_handler(int sig);
117
118 #define EVSIGBASE_LOCK() EVLOCK_LOCK(evsig_base_lock, 0)
119 #define EVSIGBASE_UNLOCK() EVLOCK_UNLOCK(evsig_base_lock, 0)
120
121 void
122 evsig_set_base_(struct event_base *base)
123 {
124         EVSIGBASE_LOCK();
125         evsig_base = base;
126         evsig_base_n_signals_added = base->sig.ev_n_signals_added;
127         evsig_base_fd = base->sig.ev_signal_pair[1];
128         EVSIGBASE_UNLOCK();
129 }
130
131 /* Callback for when the signal handler write a byte to our signaling socket */
132 static void
133 evsig_cb(evutil_socket_t fd, short what, void *arg)
134 {
135         static char signals[1024];
136         ev_ssize_t n;
137         int i;
138         int ncaught[NSIG];
139         struct event_base *base;
140
141         base = arg;
142
143         memset(&ncaught, 0, sizeof(ncaught));
144
145         while (1) {
146 #ifdef _WIN32
147                 n = recv(fd, signals, sizeof(signals), 0);
148 #else
149                 n = read(fd, signals, sizeof(signals));
150 #endif
151                 if (n == -1) {
152                         int err = evutil_socket_geterror(fd);
153                         if (! EVUTIL_ERR_RW_RETRIABLE(err))
154                                 event_sock_err(1, fd, "%s: recv", __func__);
155                         break;
156                 } else if (n == 0) {
157                         /* XXX warn? */
158                         break;
159                 }
160                 for (i = 0; i < n; ++i) {
161                         ev_uint8_t sig = signals[i];
162                         if (sig < NSIG)
163                                 ncaught[sig]++;
164                 }
165         }
166
167         EVBASE_ACQUIRE_LOCK(base, th_base_lock);
168         for (i = 0; i < NSIG; ++i) {
169                 if (ncaught[i])
170                         evmap_signal_active_(base, i, ncaught[i]);
171         }
172         EVBASE_RELEASE_LOCK(base, th_base_lock);
173 }
174
175 int
176 evsig_init_(struct event_base *base)
177 {
178         /*
179          * Our signal handler is going to write to one end of the socket
180          * pair to wake up our event loop.  The event loop then scans for
181          * signals that got delivered.
182          */
183         if (evutil_make_internal_pipe_(base->sig.ev_signal_pair) == -1) {
184 #ifdef _WIN32
185                 /* Make this nonfatal on win32, where sometimes people
186                    have localhost firewalled. */
187                 event_sock_warn(-1, "%s: socketpair", __func__);
188 #else
189                 event_sock_err(1, -1, "%s: socketpair", __func__);
190 #endif
191                 return -1;
192         }
193
194         if (base->sig.sh_old) {
195                 mm_free(base->sig.sh_old);
196         }
197         base->sig.sh_old = NULL;
198         base->sig.sh_old_max = 0;
199
200         event_assign(&base->sig.ev_signal, base, base->sig.ev_signal_pair[0],
201                 EV_READ | EV_PERSIST, evsig_cb, base);
202
203         base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL;
204         event_priority_set(&base->sig.ev_signal, 0);
205
206         base->evsigsel = &evsigops;
207
208         return 0;
209 }
210
211 /* Helper: resize saved signal handler array up to the highest signal
212    number. A dynamic array is used to keep footprint on the low side. */
213 int
214 evsig_ensure_saved_(struct evsig_info *sig, int evsignal)
215 {
216         if (evsignal >= sig->sh_old_max) {
217                 void *p;
218                 int new_max = evsignal + 1;
219                 event_debug(("%s: evsignal (%d) >= sh_old_max (%d), resizing",
220                             __func__, evsignal, sig->sh_old_max));
221                 p = mm_realloc(sig->sh_old, new_max * sizeof(*sig->sh_old));
222                 if (p == NULL) {
223                         event_warn("realloc");
224                         return (-1);
225                 }
226
227                 memset((char *)p + sig->sh_old_max * sizeof(*sig->sh_old),
228                     0, (new_max - sig->sh_old_max) * sizeof(*sig->sh_old));
229
230                 sig->sh_old_max = new_max;
231                 sig->sh_old = p;
232         }
233         return 0;
234 }
235
236 /* Helper: set the signal handler for evsignal to handler in base, so that
237  * we can restore the original handler when we clear the current one. */
238 int
239 evsig_set_handler_(struct event_base *base,
240     int evsignal, void (__cdecl *handler)(int))
241 {
242 #ifdef EVENT__HAVE_SIGACTION
243         struct sigaction sa;
244 #else
245         ev_sighandler_t sh;
246 #endif
247         struct evsig_info *sig = &base->sig;
248
249         /* ensure saved array is large enough */
250         if (evsig_ensure_saved_(sig, evsignal) < 0)
251                 return (-1);
252
253         /* allocate space for previous handler out of dynamic array */
254         sig->sh_old[evsignal] = mm_malloc(sizeof *sig->sh_old[evsignal]);
255         if (sig->sh_old[evsignal] == NULL) {
256                 event_warn("malloc");
257                 return (-1);
258         }
259
260         /* save previous handler and setup new handler */
261 #ifdef EVENT__HAVE_SIGACTION
262         memset(&sa, 0, sizeof(sa));
263         sa.sa_handler = handler;
264 #ifdef SA_RESTART
265         sa.sa_flags |= SA_RESTART;
266 #endif
267         sigfillset(&sa.sa_mask);
268
269         if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) {
270                 event_warn("sigaction");
271                 mm_free(sig->sh_old[evsignal]);
272                 sig->sh_old[evsignal] = NULL;
273                 return (-1);
274         }
275 #else
276         if ((sh = signal(evsignal, handler)) == SIG_ERR) {
277                 event_warn("signal");
278                 mm_free(sig->sh_old[evsignal]);
279                 sig->sh_old[evsignal] = NULL;
280                 return (-1);
281         }
282         *sig->sh_old[evsignal] = sh;
283 #endif
284
285         return (0);
286 }
287
288 static int
289 evsig_add(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p)
290 {
291         struct evsig_info *sig = &base->sig;
292         (void)p;
293
294         EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG);
295
296         /* catch signals if they happen quickly */
297         EVSIGBASE_LOCK();
298         if (evsig_base != base && evsig_base_n_signals_added) {
299                 event_warnx("Added a signal to event base %p with signals "
300                     "already added to event_base %p.  Only one can have "
301                     "signals at a time with the %s backend.  The base with "
302                     "the most recently added signal or the most recent "
303                     "event_base_loop() call gets preference; do "
304                     "not rely on this behavior in future Libevent versions.",
305                    (void *)base, (void *)evsig_base, base->evsel->name);
306         }
307         evsig_base = base;
308         evsig_base_n_signals_added = ++sig->ev_n_signals_added;
309         evsig_base_fd = base->sig.ev_signal_pair[1];
310         EVSIGBASE_UNLOCK();
311
312         event_debug(("%s: %d: changing signal handler", __func__, (int)evsignal));
313         if (evsig_set_handler_(base, (int)evsignal, evsig_handler) == -1) {
314                 goto err;
315         }
316
317
318         if (!sig->ev_signal_added) {
319                 if (event_add_nolock_(&sig->ev_signal, NULL, 0))
320                         goto err;
321                 sig->ev_signal_added = 1;
322         }
323
324         return (0);
325
326 err:
327         EVSIGBASE_LOCK();
328         --evsig_base_n_signals_added;
329         --sig->ev_n_signals_added;
330         EVSIGBASE_UNLOCK();
331         return (-1);
332 }
333
334 int
335 evsig_restore_handler_(struct event_base *base, int evsignal)
336 {
337         int ret = 0;
338         struct evsig_info *sig = &base->sig;
339 #ifdef EVENT__HAVE_SIGACTION
340         struct sigaction *sh;
341 #else
342         ev_sighandler_t *sh;
343 #endif
344
345         if (evsignal >= sig->sh_old_max) {
346                 /* Can't actually restore. */
347                 /* XXXX.*/
348                 return 0;
349         }
350
351         /* restore previous handler */
352         sh = sig->sh_old[evsignal];
353         sig->sh_old[evsignal] = NULL;
354 #ifdef EVENT__HAVE_SIGACTION
355         if (sigaction(evsignal, sh, NULL) == -1) {
356                 event_warn("sigaction");
357                 ret = -1;
358         }
359 #else
360         if (signal(evsignal, *sh) == SIG_ERR) {
361                 event_warn("signal");
362                 ret = -1;
363         }
364 #endif
365
366         mm_free(sh);
367
368         return ret;
369 }
370
371 static int
372 evsig_del(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p)
373 {
374         EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG);
375
376         event_debug(("%s: "EV_SOCK_FMT": restoring signal handler",
377                 __func__, EV_SOCK_ARG(evsignal)));
378
379         EVSIGBASE_LOCK();
380         --evsig_base_n_signals_added;
381         --base->sig.ev_n_signals_added;
382         EVSIGBASE_UNLOCK();
383
384         return (evsig_restore_handler_(base, (int)evsignal));
385 }
386
387 static void __cdecl
388 evsig_handler(int sig)
389 {
390         int save_errno = errno;
391 #ifdef _WIN32
392         int socket_errno = EVUTIL_SOCKET_ERROR();
393 #endif
394         ev_uint8_t msg;
395
396         if (evsig_base == NULL) {
397                 event_warnx(
398                         "%s: received signal %d, but have no base configured",
399                         __func__, sig);
400                 return;
401         }
402
403 #ifndef EVENT__HAVE_SIGACTION
404         signal(sig, evsig_handler);
405 #endif
406
407         /* Wake up our notification mechanism */
408         msg = sig;
409 #ifdef _WIN32
410         send(evsig_base_fd, (char*)&msg, 1, 0);
411 #else
412         for (;;) {
413                 /*
414                  * errno is only set to provide a descriptive message for event_warnx
415                  * if write returns 0. Not setting it will result in "No error" message
416                  * because write does not set errno when returning 0.
417                  *
418                  * EAGAIN will print "Try again" message. Another idea is to use
419                  * ENOSPC, but since we use non blocking sockets EAGAIN is preferable.
420                  *
421                  * Other than setting this text of the logged warning, the value in
422                  * errno has no further effect.
423                  */
424                 errno = EAGAIN;
425                 if (0 >= write(evsig_base_fd, &msg, 1)) {
426                         if (errno == EINTR)
427                                 continue;
428                         event_warnx("%s: write: %s", __func__, strerror(errno));
429                 }
430                 break;
431         }
432 #endif
433         errno = save_errno;
434 #ifdef _WIN32
435         EVUTIL_SET_SOCKET_ERROR(socket_errno);
436 #endif
437 }
438
439 void
440 evsig_dealloc_(struct event_base *base)
441 {
442         int i = 0;
443         if (base->sig.ev_signal_added) {
444                 event_del(&base->sig.ev_signal);
445                 base->sig.ev_signal_added = 0;
446         }
447         /* debug event is created in evsig_init_/event_assign even when
448          * ev_signal_added == 0, so unassign is required */
449         event_debug_unassign(&base->sig.ev_signal);
450
451         for (i = 0; i < NSIG; ++i) {
452                 if (i < base->sig.sh_old_max && base->sig.sh_old[i] != NULL)
453                         evsig_restore_handler_(base, i);
454         }
455         EVSIGBASE_LOCK();
456         if (base == evsig_base) {
457                 evsig_base = NULL;
458                 evsig_base_n_signals_added = 0;
459                 evsig_base_fd = -1;
460         }
461         EVSIGBASE_UNLOCK();
462
463         if (base->sig.ev_signal_pair[0] != -1) {
464                 evutil_closesocket(base->sig.ev_signal_pair[0]);
465                 base->sig.ev_signal_pair[0] = -1;
466         }
467         if (base->sig.ev_signal_pair[1] != -1) {
468                 evutil_closesocket(base->sig.ev_signal_pair[1]);
469                 base->sig.ev_signal_pair[1] = -1;
470         }
471         base->sig.sh_old_max = 0;
472
473         /* per index frees are handled in evsig_del() */
474         if (base->sig.sh_old) {
475                 mm_free(base->sig.sh_old);
476                 base->sig.sh_old = NULL;
477         }
478 }
479
480 static void
481 evsig_free_globals_locks(void)
482 {
483 #ifndef EVENT__DISABLE_THREAD_SUPPORT
484         if (evsig_base_lock != NULL) {
485                 EVTHREAD_FREE_LOCK(evsig_base_lock, 0);
486                 evsig_base_lock = NULL;
487         }
488 #endif
489         return;
490 }
491
492 void
493 evsig_free_globals_(void)
494 {
495         evsig_free_globals_locks();
496 }
497
498 #ifndef EVENT__DISABLE_THREAD_SUPPORT
499 int
500 evsig_global_setup_locks_(const int enable_locks)
501 {
502         EVTHREAD_SETUP_GLOBAL_LOCK(evsig_base_lock, 0);
503         return 0;
504 }
505
506 #endif