xref: /freebsd/contrib/ntp/sntp/libevent/signal.c (revision a466cc55)
12b15cb3dSCy Schubert /*	$OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $	*/
22b15cb3dSCy Schubert 
32b15cb3dSCy Schubert /*
42b15cb3dSCy Schubert  * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu>
52b15cb3dSCy Schubert  * Copyright 2007-2012 Niels Provos and Nick Mathewson
62b15cb3dSCy Schubert  *
72b15cb3dSCy Schubert  * Redistribution and use in source and binary forms, with or without
82b15cb3dSCy Schubert  * modification, are permitted provided that the following conditions
92b15cb3dSCy Schubert  * are met:
102b15cb3dSCy Schubert  * 1. Redistributions of source code must retain the above copyright
112b15cb3dSCy Schubert  *    notice, this list of conditions and the following disclaimer.
122b15cb3dSCy Schubert  * 2. Redistributions in binary form must reproduce the above copyright
132b15cb3dSCy Schubert  *    notice, this list of conditions and the following disclaimer in the
142b15cb3dSCy Schubert  *    documentation and/or other materials provided with the distribution.
152b15cb3dSCy Schubert  * 3. The name of the author may not be used to endorse or promote products
162b15cb3dSCy Schubert  *    derived from this software without specific prior written permission.
172b15cb3dSCy Schubert  *
182b15cb3dSCy Schubert  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
192b15cb3dSCy Schubert  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
202b15cb3dSCy Schubert  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
212b15cb3dSCy Schubert  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
222b15cb3dSCy Schubert  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
232b15cb3dSCy Schubert  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
242b15cb3dSCy Schubert  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
252b15cb3dSCy Schubert  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
262b15cb3dSCy Schubert  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
272b15cb3dSCy Schubert  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
282b15cb3dSCy Schubert  */
292b15cb3dSCy Schubert #include "event2/event-config.h"
302b15cb3dSCy Schubert #include "evconfig-private.h"
312b15cb3dSCy Schubert 
322b15cb3dSCy Schubert #ifdef _WIN32
332b15cb3dSCy Schubert #define WIN32_LEAN_AND_MEAN
342b15cb3dSCy Schubert #include <winsock2.h>
352b15cb3dSCy Schubert #include <windows.h>
362b15cb3dSCy Schubert #undef WIN32_LEAN_AND_MEAN
372b15cb3dSCy Schubert #endif
382b15cb3dSCy Schubert #include <sys/types.h>
392b15cb3dSCy Schubert #ifdef EVENT__HAVE_SYS_TIME_H
402b15cb3dSCy Schubert #include <sys/time.h>
412b15cb3dSCy Schubert #endif
422b15cb3dSCy Schubert #include <sys/queue.h>
432b15cb3dSCy Schubert #ifdef EVENT__HAVE_SYS_SOCKET_H
442b15cb3dSCy Schubert #include <sys/socket.h>
452b15cb3dSCy Schubert #endif
462b15cb3dSCy Schubert #include <signal.h>
472b15cb3dSCy Schubert #include <stdio.h>
482b15cb3dSCy Schubert #include <stdlib.h>
492b15cb3dSCy Schubert #include <string.h>
502b15cb3dSCy Schubert #ifdef EVENT__HAVE_UNISTD_H
512b15cb3dSCy Schubert #include <unistd.h>
522b15cb3dSCy Schubert #endif
532b15cb3dSCy Schubert #include <errno.h>
542b15cb3dSCy Schubert #ifdef EVENT__HAVE_FCNTL_H
552b15cb3dSCy Schubert #include <fcntl.h>
562b15cb3dSCy Schubert #endif
572b15cb3dSCy Schubert 
582b15cb3dSCy Schubert #include "event2/event.h"
592b15cb3dSCy Schubert #include "event2/event_struct.h"
602b15cb3dSCy Schubert #include "event-internal.h"
612b15cb3dSCy Schubert #include "event2/util.h"
622b15cb3dSCy Schubert #include "evsignal-internal.h"
632b15cb3dSCy Schubert #include "log-internal.h"
642b15cb3dSCy Schubert #include "evmap-internal.h"
652b15cb3dSCy Schubert #include "evthread-internal.h"
662b15cb3dSCy Schubert 
672b15cb3dSCy Schubert /*
682b15cb3dSCy Schubert   signal.c
692b15cb3dSCy Schubert 
702b15cb3dSCy Schubert   This is the signal-handling implementation we use for backends that don't
712b15cb3dSCy Schubert   have a better way to do signal handling.  It uses sigaction() or signal()
722b15cb3dSCy Schubert   to set a signal handler, and a socket pair to tell the event base when
732b15cb3dSCy Schubert 
742b15cb3dSCy Schubert   Note that I said "the event base" : only one event base can be set up to use
752b15cb3dSCy Schubert   this at a time.  For historical reasons and backward compatibility, if you
762b15cb3dSCy Schubert   add an event for a signal to event_base A, then add an event for a signal
772b15cb3dSCy Schubert   (any signal!) to event_base B, event_base B will get informed about the
782b15cb3dSCy Schubert   signal, but event_base A won't.
792b15cb3dSCy Schubert 
802b15cb3dSCy Schubert   It would be neat to change this behavior in some future version of Libevent.
812b15cb3dSCy Schubert   kqueue already does something far more sensible.  We can make all backends
822b15cb3dSCy Schubert   on Linux do a reasonable thing using signalfd.
832b15cb3dSCy Schubert */
842b15cb3dSCy Schubert 
852b15cb3dSCy Schubert #ifndef _WIN32
862b15cb3dSCy Schubert /* Windows wants us to call our signal handlers as __cdecl.  Nobody else
872b15cb3dSCy Schubert  * expects you to do anything crazy like this. */
88*a466cc55SCy Schubert #ifndef __cdecl
892b15cb3dSCy Schubert #define __cdecl
902b15cb3dSCy Schubert #endif
91*a466cc55SCy Schubert #endif
922b15cb3dSCy Schubert 
932b15cb3dSCy Schubert static int evsig_add(struct event_base *, evutil_socket_t, short, short, void *);
942b15cb3dSCy Schubert static int evsig_del(struct event_base *, evutil_socket_t, short, short, void *);
952b15cb3dSCy Schubert 
962b15cb3dSCy Schubert static const struct eventop evsigops = {
972b15cb3dSCy Schubert 	"signal",
982b15cb3dSCy Schubert 	NULL,
992b15cb3dSCy Schubert 	evsig_add,
1002b15cb3dSCy Schubert 	evsig_del,
1012b15cb3dSCy Schubert 	NULL,
1022b15cb3dSCy Schubert 	NULL,
1032b15cb3dSCy Schubert 	0, 0, 0
1042b15cb3dSCy Schubert };
1052b15cb3dSCy Schubert 
1062b15cb3dSCy Schubert #ifndef EVENT__DISABLE_THREAD_SUPPORT
1072b15cb3dSCy Schubert /* Lock for evsig_base and evsig_base_n_signals_added fields. */
1082b15cb3dSCy Schubert static void *evsig_base_lock = NULL;
1092b15cb3dSCy Schubert #endif
1102b15cb3dSCy Schubert /* The event base that's currently getting informed about signals. */
1112b15cb3dSCy Schubert static struct event_base *evsig_base = NULL;
1122b15cb3dSCy Schubert /* A copy of evsig_base->sigev_n_signals_added. */
1132b15cb3dSCy Schubert static int evsig_base_n_signals_added = 0;
1142b15cb3dSCy Schubert static evutil_socket_t evsig_base_fd = -1;
1152b15cb3dSCy Schubert 
1162b15cb3dSCy Schubert static void __cdecl evsig_handler(int sig);
1172b15cb3dSCy Schubert 
1182b15cb3dSCy Schubert #define EVSIGBASE_LOCK() EVLOCK_LOCK(evsig_base_lock, 0)
1192b15cb3dSCy Schubert #define EVSIGBASE_UNLOCK() EVLOCK_UNLOCK(evsig_base_lock, 0)
1202b15cb3dSCy Schubert 
1212b15cb3dSCy Schubert void
evsig_set_base_(struct event_base * base)1222b15cb3dSCy Schubert evsig_set_base_(struct event_base *base)
1232b15cb3dSCy Schubert {
1242b15cb3dSCy Schubert 	EVSIGBASE_LOCK();
1252b15cb3dSCy Schubert 	evsig_base = base;
1262b15cb3dSCy Schubert 	evsig_base_n_signals_added = base->sig.ev_n_signals_added;
1272b15cb3dSCy Schubert 	evsig_base_fd = base->sig.ev_signal_pair[1];
1282b15cb3dSCy Schubert 	EVSIGBASE_UNLOCK();
1292b15cb3dSCy Schubert }
1302b15cb3dSCy Schubert 
1312b15cb3dSCy Schubert /* Callback for when the signal handler write a byte to our signaling socket */
1322b15cb3dSCy Schubert static void
evsig_cb(evutil_socket_t fd,short what,void * arg)1332b15cb3dSCy Schubert evsig_cb(evutil_socket_t fd, short what, void *arg)
1342b15cb3dSCy Schubert {
1352b15cb3dSCy Schubert 	static char signals[1024];
1362b15cb3dSCy Schubert 	ev_ssize_t n;
1372b15cb3dSCy Schubert 	int i;
1382b15cb3dSCy Schubert 	int ncaught[NSIG];
1392b15cb3dSCy Schubert 	struct event_base *base;
1402b15cb3dSCy Schubert 
1412b15cb3dSCy Schubert 	base = arg;
1422b15cb3dSCy Schubert 
1432b15cb3dSCy Schubert 	memset(&ncaught, 0, sizeof(ncaught));
1442b15cb3dSCy Schubert 
1452b15cb3dSCy Schubert 	while (1) {
1462b15cb3dSCy Schubert #ifdef _WIN32
1472b15cb3dSCy Schubert 		n = recv(fd, signals, sizeof(signals), 0);
1482b15cb3dSCy Schubert #else
1492b15cb3dSCy Schubert 		n = read(fd, signals, sizeof(signals));
1502b15cb3dSCy Schubert #endif
1512b15cb3dSCy Schubert 		if (n == -1) {
1522b15cb3dSCy Schubert 			int err = evutil_socket_geterror(fd);
1532b15cb3dSCy Schubert 			if (! EVUTIL_ERR_RW_RETRIABLE(err))
1542b15cb3dSCy Schubert 				event_sock_err(1, fd, "%s: recv", __func__);
1552b15cb3dSCy Schubert 			break;
1562b15cb3dSCy Schubert 		} else if (n == 0) {
1572b15cb3dSCy Schubert 			/* XXX warn? */
1582b15cb3dSCy Schubert 			break;
1592b15cb3dSCy Schubert 		}
1602b15cb3dSCy Schubert 		for (i = 0; i < n; ++i) {
1612b15cb3dSCy Schubert 			ev_uint8_t sig = signals[i];
1622b15cb3dSCy Schubert 			if (sig < NSIG)
1632b15cb3dSCy Schubert 				ncaught[sig]++;
1642b15cb3dSCy Schubert 		}
1652b15cb3dSCy Schubert 	}
1662b15cb3dSCy Schubert 
1672b15cb3dSCy Schubert 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
1682b15cb3dSCy Schubert 	for (i = 0; i < NSIG; ++i) {
1692b15cb3dSCy Schubert 		if (ncaught[i])
1702b15cb3dSCy Schubert 			evmap_signal_active_(base, i, ncaught[i]);
1712b15cb3dSCy Schubert 	}
1722b15cb3dSCy Schubert 	EVBASE_RELEASE_LOCK(base, th_base_lock);
1732b15cb3dSCy Schubert }
1742b15cb3dSCy Schubert 
1752b15cb3dSCy Schubert int
evsig_init_(struct event_base * base)1762b15cb3dSCy Schubert evsig_init_(struct event_base *base)
1772b15cb3dSCy Schubert {
1782b15cb3dSCy Schubert 	/*
1792b15cb3dSCy Schubert 	 * Our signal handler is going to write to one end of the socket
1802b15cb3dSCy Schubert 	 * pair to wake up our event loop.  The event loop then scans for
1812b15cb3dSCy Schubert 	 * signals that got delivered.
1822b15cb3dSCy Schubert 	 */
1832b15cb3dSCy Schubert 	if (evutil_make_internal_pipe_(base->sig.ev_signal_pair) == -1) {
1842b15cb3dSCy Schubert #ifdef _WIN32
1852b15cb3dSCy Schubert 		/* Make this nonfatal on win32, where sometimes people
1862b15cb3dSCy Schubert 		   have localhost firewalled. */
1872b15cb3dSCy Schubert 		event_sock_warn(-1, "%s: socketpair", __func__);
1882b15cb3dSCy Schubert #else
1892b15cb3dSCy Schubert 		event_sock_err(1, -1, "%s: socketpair", __func__);
1902b15cb3dSCy Schubert #endif
1912b15cb3dSCy Schubert 		return -1;
1922b15cb3dSCy Schubert 	}
1932b15cb3dSCy Schubert 
1942b15cb3dSCy Schubert 	if (base->sig.sh_old) {
1952b15cb3dSCy Schubert 		mm_free(base->sig.sh_old);
1962b15cb3dSCy Schubert 	}
1972b15cb3dSCy Schubert 	base->sig.sh_old = NULL;
1982b15cb3dSCy Schubert 	base->sig.sh_old_max = 0;
1992b15cb3dSCy Schubert 
2002b15cb3dSCy Schubert 	event_assign(&base->sig.ev_signal, base, base->sig.ev_signal_pair[0],
2012b15cb3dSCy Schubert 		EV_READ | EV_PERSIST, evsig_cb, base);
2022b15cb3dSCy Schubert 
2032b15cb3dSCy Schubert 	base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL;
2042b15cb3dSCy Schubert 	event_priority_set(&base->sig.ev_signal, 0);
2052b15cb3dSCy Schubert 
2062b15cb3dSCy Schubert 	base->evsigsel = &evsigops;
2072b15cb3dSCy Schubert 
2082b15cb3dSCy Schubert 	return 0;
2092b15cb3dSCy Schubert }
2102b15cb3dSCy Schubert 
2112b15cb3dSCy Schubert /* Helper: set the signal handler for evsignal to handler in base, so that
2122b15cb3dSCy Schubert  * we can restore the original handler when we clear the current one. */
2132b15cb3dSCy Schubert int
evsig_set_handler_(struct event_base * base,int evsignal,void (__cdecl * handler)(int))2142b15cb3dSCy Schubert evsig_set_handler_(struct event_base *base,
2152b15cb3dSCy Schubert     int evsignal, void (__cdecl *handler)(int))
2162b15cb3dSCy Schubert {
2172b15cb3dSCy Schubert #ifdef EVENT__HAVE_SIGACTION
2182b15cb3dSCy Schubert 	struct sigaction sa;
2192b15cb3dSCy Schubert #else
2202b15cb3dSCy Schubert 	ev_sighandler_t sh;
2212b15cb3dSCy Schubert #endif
2222b15cb3dSCy Schubert 	struct evsig_info *sig = &base->sig;
2232b15cb3dSCy Schubert 	void *p;
2242b15cb3dSCy Schubert 
2252b15cb3dSCy Schubert 	/*
2262b15cb3dSCy Schubert 	 * resize saved signal handler array up to the highest signal number.
2272b15cb3dSCy Schubert 	 * a dynamic array is used to keep footprint on the low side.
2282b15cb3dSCy Schubert 	 */
2292b15cb3dSCy Schubert 	if (evsignal >= sig->sh_old_max) {
2302b15cb3dSCy Schubert 		int new_max = evsignal + 1;
2312b15cb3dSCy Schubert 		event_debug(("%s: evsignal (%d) >= sh_old_max (%d), resizing",
2322b15cb3dSCy Schubert 			    __func__, evsignal, sig->sh_old_max));
2332b15cb3dSCy Schubert 		p = mm_realloc(sig->sh_old, new_max * sizeof(*sig->sh_old));
2342b15cb3dSCy Schubert 		if (p == NULL) {
2352b15cb3dSCy Schubert 			event_warn("realloc");
2362b15cb3dSCy Schubert 			return (-1);
2372b15cb3dSCy Schubert 		}
2382b15cb3dSCy Schubert 
2392b15cb3dSCy Schubert 		memset((char *)p + sig->sh_old_max * sizeof(*sig->sh_old),
2402b15cb3dSCy Schubert 		    0, (new_max - sig->sh_old_max) * sizeof(*sig->sh_old));
2412b15cb3dSCy Schubert 
2422b15cb3dSCy Schubert 		sig->sh_old_max = new_max;
2432b15cb3dSCy Schubert 		sig->sh_old = p;
2442b15cb3dSCy Schubert 	}
2452b15cb3dSCy Schubert 
2462b15cb3dSCy Schubert 	/* allocate space for previous handler out of dynamic array */
2472b15cb3dSCy Schubert 	sig->sh_old[evsignal] = mm_malloc(sizeof *sig->sh_old[evsignal]);
2482b15cb3dSCy Schubert 	if (sig->sh_old[evsignal] == NULL) {
2492b15cb3dSCy Schubert 		event_warn("malloc");
2502b15cb3dSCy Schubert 		return (-1);
2512b15cb3dSCy Schubert 	}
2522b15cb3dSCy Schubert 
2532b15cb3dSCy Schubert 	/* save previous handler and setup new handler */
2542b15cb3dSCy Schubert #ifdef EVENT__HAVE_SIGACTION
2552b15cb3dSCy Schubert 	memset(&sa, 0, sizeof(sa));
2562b15cb3dSCy Schubert 	sa.sa_handler = handler;
2572b15cb3dSCy Schubert 	sa.sa_flags |= SA_RESTART;
2582b15cb3dSCy Schubert 	sigfillset(&sa.sa_mask);
2592b15cb3dSCy Schubert 
2602b15cb3dSCy Schubert 	if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) {
2612b15cb3dSCy Schubert 		event_warn("sigaction");
2622b15cb3dSCy Schubert 		mm_free(sig->sh_old[evsignal]);
2632b15cb3dSCy Schubert 		sig->sh_old[evsignal] = NULL;
2642b15cb3dSCy Schubert 		return (-1);
2652b15cb3dSCy Schubert 	}
2662b15cb3dSCy Schubert #else
2672b15cb3dSCy Schubert 	if ((sh = signal(evsignal, handler)) == SIG_ERR) {
2682b15cb3dSCy Schubert 		event_warn("signal");
2692b15cb3dSCy Schubert 		mm_free(sig->sh_old[evsignal]);
2702b15cb3dSCy Schubert 		sig->sh_old[evsignal] = NULL;
2712b15cb3dSCy Schubert 		return (-1);
2722b15cb3dSCy Schubert 	}
2732b15cb3dSCy Schubert 	*sig->sh_old[evsignal] = sh;
2742b15cb3dSCy Schubert #endif
2752b15cb3dSCy Schubert 
2762b15cb3dSCy Schubert 	return (0);
2772b15cb3dSCy Schubert }
2782b15cb3dSCy Schubert 
2792b15cb3dSCy Schubert static int
evsig_add(struct event_base * base,evutil_socket_t evsignal,short old,short events,void * p)2802b15cb3dSCy Schubert evsig_add(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p)
2812b15cb3dSCy Schubert {
2822b15cb3dSCy Schubert 	struct evsig_info *sig = &base->sig;
2832b15cb3dSCy Schubert 	(void)p;
2842b15cb3dSCy Schubert 
2852b15cb3dSCy Schubert 	EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG);
2862b15cb3dSCy Schubert 
2872b15cb3dSCy Schubert 	/* catch signals if they happen quickly */
2882b15cb3dSCy Schubert 	EVSIGBASE_LOCK();
2892b15cb3dSCy Schubert 	if (evsig_base != base && evsig_base_n_signals_added) {
2902b15cb3dSCy Schubert 		event_warnx("Added a signal to event base %p with signals "
2912b15cb3dSCy Schubert 		    "already added to event_base %p.  Only one can have "
2922b15cb3dSCy Schubert 		    "signals at a time with the %s backend.  The base with "
2932b15cb3dSCy Schubert 		    "the most recently added signal or the most recent "
2942b15cb3dSCy Schubert 		    "event_base_loop() call gets preference; do "
2952b15cb3dSCy Schubert 		    "not rely on this behavior in future Libevent versions.",
2962b15cb3dSCy Schubert 		    base, evsig_base, base->evsel->name);
2972b15cb3dSCy Schubert 	}
2982b15cb3dSCy Schubert 	evsig_base = base;
2992b15cb3dSCy Schubert 	evsig_base_n_signals_added = ++sig->ev_n_signals_added;
3002b15cb3dSCy Schubert 	evsig_base_fd = base->sig.ev_signal_pair[1];
3012b15cb3dSCy Schubert 	EVSIGBASE_UNLOCK();
3022b15cb3dSCy Schubert 
3032b15cb3dSCy Schubert 	event_debug(("%s: %d: changing signal handler", __func__, (int)evsignal));
3042b15cb3dSCy Schubert 	if (evsig_set_handler_(base, (int)evsignal, evsig_handler) == -1) {
3052b15cb3dSCy Schubert 		goto err;
3062b15cb3dSCy Schubert 	}
3072b15cb3dSCy Schubert 
3082b15cb3dSCy Schubert 
3092b15cb3dSCy Schubert 	if (!sig->ev_signal_added) {
3102b15cb3dSCy Schubert 		if (event_add_nolock_(&sig->ev_signal, NULL, 0))
3112b15cb3dSCy Schubert 			goto err;
3122b15cb3dSCy Schubert 		sig->ev_signal_added = 1;
3132b15cb3dSCy Schubert 	}
3142b15cb3dSCy Schubert 
3152b15cb3dSCy Schubert 	return (0);
3162b15cb3dSCy Schubert 
3172b15cb3dSCy Schubert err:
3182b15cb3dSCy Schubert 	EVSIGBASE_LOCK();
3192b15cb3dSCy Schubert 	--evsig_base_n_signals_added;
3202b15cb3dSCy Schubert 	--sig->ev_n_signals_added;
3212b15cb3dSCy Schubert 	EVSIGBASE_UNLOCK();
3222b15cb3dSCy Schubert 	return (-1);
3232b15cb3dSCy Schubert }
3242b15cb3dSCy Schubert 
3252b15cb3dSCy Schubert int
evsig_restore_handler_(struct event_base * base,int evsignal)3262b15cb3dSCy Schubert evsig_restore_handler_(struct event_base *base, int evsignal)
3272b15cb3dSCy Schubert {
3282b15cb3dSCy Schubert 	int ret = 0;
3292b15cb3dSCy Schubert 	struct evsig_info *sig = &base->sig;
3302b15cb3dSCy Schubert #ifdef EVENT__HAVE_SIGACTION
3312b15cb3dSCy Schubert 	struct sigaction *sh;
3322b15cb3dSCy Schubert #else
3332b15cb3dSCy Schubert 	ev_sighandler_t *sh;
3342b15cb3dSCy Schubert #endif
3352b15cb3dSCy Schubert 
3362b15cb3dSCy Schubert 	if (evsignal >= sig->sh_old_max) {
3372b15cb3dSCy Schubert 		/* Can't actually restore. */
3382b15cb3dSCy Schubert 		/* XXXX.*/
3392b15cb3dSCy Schubert 		return 0;
3402b15cb3dSCy Schubert 	}
3412b15cb3dSCy Schubert 
3422b15cb3dSCy Schubert 	/* restore previous handler */
3432b15cb3dSCy Schubert 	sh = sig->sh_old[evsignal];
3442b15cb3dSCy Schubert 	sig->sh_old[evsignal] = NULL;
3452b15cb3dSCy Schubert #ifdef EVENT__HAVE_SIGACTION
3462b15cb3dSCy Schubert 	if (sigaction(evsignal, sh, NULL) == -1) {
3472b15cb3dSCy Schubert 		event_warn("sigaction");
3482b15cb3dSCy Schubert 		ret = -1;
3492b15cb3dSCy Schubert 	}
3502b15cb3dSCy Schubert #else
3512b15cb3dSCy Schubert 	if (signal(evsignal, *sh) == SIG_ERR) {
3522b15cb3dSCy Schubert 		event_warn("signal");
3532b15cb3dSCy Schubert 		ret = -1;
3542b15cb3dSCy Schubert 	}
3552b15cb3dSCy Schubert #endif
3562b15cb3dSCy Schubert 
3572b15cb3dSCy Schubert 	mm_free(sh);
3582b15cb3dSCy Schubert 
3592b15cb3dSCy Schubert 	return ret;
3602b15cb3dSCy Schubert }
3612b15cb3dSCy Schubert 
3622b15cb3dSCy Schubert static int
evsig_del(struct event_base * base,evutil_socket_t evsignal,short old,short events,void * p)3632b15cb3dSCy Schubert evsig_del(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p)
3642b15cb3dSCy Schubert {
3652b15cb3dSCy Schubert 	EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG);
3662b15cb3dSCy Schubert 
3672b15cb3dSCy Schubert 	event_debug(("%s: "EV_SOCK_FMT": restoring signal handler",
3682b15cb3dSCy Schubert 		__func__, EV_SOCK_ARG(evsignal)));
3692b15cb3dSCy Schubert 
3702b15cb3dSCy Schubert 	EVSIGBASE_LOCK();
3712b15cb3dSCy Schubert 	--evsig_base_n_signals_added;
3722b15cb3dSCy Schubert 	--base->sig.ev_n_signals_added;
3732b15cb3dSCy Schubert 	EVSIGBASE_UNLOCK();
3742b15cb3dSCy Schubert 
3752b15cb3dSCy Schubert 	return (evsig_restore_handler_(base, (int)evsignal));
3762b15cb3dSCy Schubert }
3772b15cb3dSCy Schubert 
3782b15cb3dSCy Schubert static void __cdecl
evsig_handler(int sig)3792b15cb3dSCy Schubert evsig_handler(int sig)
3802b15cb3dSCy Schubert {
3812b15cb3dSCy Schubert 	int save_errno = errno;
3822b15cb3dSCy Schubert #ifdef _WIN32
3832b15cb3dSCy Schubert 	int socket_errno = EVUTIL_SOCKET_ERROR();
3842b15cb3dSCy Schubert #endif
3852b15cb3dSCy Schubert 	ev_uint8_t msg;
3862b15cb3dSCy Schubert 
3872b15cb3dSCy Schubert 	if (evsig_base == NULL) {
3882b15cb3dSCy Schubert 		event_warnx(
3892b15cb3dSCy Schubert 			"%s: received signal %d, but have no base configured",
3902b15cb3dSCy Schubert 			__func__, sig);
3912b15cb3dSCy Schubert 		return;
3922b15cb3dSCy Schubert 	}
3932b15cb3dSCy Schubert 
3942b15cb3dSCy Schubert #ifndef EVENT__HAVE_SIGACTION
3952b15cb3dSCy Schubert 	signal(sig, evsig_handler);
3962b15cb3dSCy Schubert #endif
3972b15cb3dSCy Schubert 
3982b15cb3dSCy Schubert 	/* Wake up our notification mechanism */
3992b15cb3dSCy Schubert 	msg = sig;
4002b15cb3dSCy Schubert #ifdef _WIN32
4012b15cb3dSCy Schubert 	send(evsig_base_fd, (char*)&msg, 1, 0);
4022b15cb3dSCy Schubert #else
4032b15cb3dSCy Schubert 	{
4042b15cb3dSCy Schubert 		int r = write(evsig_base_fd, (char*)&msg, 1);
4052b15cb3dSCy Schubert 		(void)r; /* Suppress 'unused return value' and 'unused var' */
4062b15cb3dSCy Schubert 	}
4072b15cb3dSCy Schubert #endif
4082b15cb3dSCy Schubert 	errno = save_errno;
4092b15cb3dSCy Schubert #ifdef _WIN32
4102b15cb3dSCy Schubert 	EVUTIL_SET_SOCKET_ERROR(socket_errno);
4112b15cb3dSCy Schubert #endif
4122b15cb3dSCy Schubert }
4132b15cb3dSCy Schubert 
4142b15cb3dSCy Schubert void
evsig_dealloc_(struct event_base * base)4152b15cb3dSCy Schubert evsig_dealloc_(struct event_base *base)
4162b15cb3dSCy Schubert {
4172b15cb3dSCy Schubert 	int i = 0;
4182b15cb3dSCy Schubert 	if (base->sig.ev_signal_added) {
4192b15cb3dSCy Schubert 		event_del(&base->sig.ev_signal);
4202b15cb3dSCy Schubert 		base->sig.ev_signal_added = 0;
4212b15cb3dSCy Schubert 	}
4222b15cb3dSCy Schubert 	/* debug event is created in evsig_init_/event_assign even when
4232b15cb3dSCy Schubert 	 * ev_signal_added == 0, so unassign is required */
4242b15cb3dSCy Schubert 	event_debug_unassign(&base->sig.ev_signal);
4252b15cb3dSCy Schubert 
4262b15cb3dSCy Schubert 	for (i = 0; i < NSIG; ++i) {
4272b15cb3dSCy Schubert 		if (i < base->sig.sh_old_max && base->sig.sh_old[i] != NULL)
4282b15cb3dSCy Schubert 			evsig_restore_handler_(base, i);
4292b15cb3dSCy Schubert 	}
4302b15cb3dSCy Schubert 	EVSIGBASE_LOCK();
4312b15cb3dSCy Schubert 	if (base == evsig_base) {
4322b15cb3dSCy Schubert 		evsig_base = NULL;
4332b15cb3dSCy Schubert 		evsig_base_n_signals_added = 0;
4342b15cb3dSCy Schubert 		evsig_base_fd = -1;
4352b15cb3dSCy Schubert 	}
4362b15cb3dSCy Schubert 	EVSIGBASE_UNLOCK();
4372b15cb3dSCy Schubert 
4382b15cb3dSCy Schubert 	if (base->sig.ev_signal_pair[0] != -1) {
4392b15cb3dSCy Schubert 		evutil_closesocket(base->sig.ev_signal_pair[0]);
4402b15cb3dSCy Schubert 		base->sig.ev_signal_pair[0] = -1;
4412b15cb3dSCy Schubert 	}
4422b15cb3dSCy Schubert 	if (base->sig.ev_signal_pair[1] != -1) {
4432b15cb3dSCy Schubert 		evutil_closesocket(base->sig.ev_signal_pair[1]);
4442b15cb3dSCy Schubert 		base->sig.ev_signal_pair[1] = -1;
4452b15cb3dSCy Schubert 	}
4462b15cb3dSCy Schubert 	base->sig.sh_old_max = 0;
4472b15cb3dSCy Schubert 
4482b15cb3dSCy Schubert 	/* per index frees are handled in evsig_del() */
4492b15cb3dSCy Schubert 	if (base->sig.sh_old) {
4502b15cb3dSCy Schubert 		mm_free(base->sig.sh_old);
4512b15cb3dSCy Schubert 		base->sig.sh_old = NULL;
4522b15cb3dSCy Schubert 	}
4532b15cb3dSCy Schubert }
4542b15cb3dSCy Schubert 
4552b15cb3dSCy Schubert static void
evsig_free_globals_locks(void)4562b15cb3dSCy Schubert evsig_free_globals_locks(void)
4572b15cb3dSCy Schubert {
4582b15cb3dSCy Schubert #ifndef EVENT__DISABLE_THREAD_SUPPORT
4592b15cb3dSCy Schubert 	if (evsig_base_lock != NULL) {
4602b15cb3dSCy Schubert 		EVTHREAD_FREE_LOCK(evsig_base_lock, 0);
4612b15cb3dSCy Schubert 		evsig_base_lock = NULL;
4622b15cb3dSCy Schubert 	}
4632b15cb3dSCy Schubert #endif
4642b15cb3dSCy Schubert 	return;
4652b15cb3dSCy Schubert }
4662b15cb3dSCy Schubert 
4672b15cb3dSCy Schubert void
evsig_free_globals_(void)4682b15cb3dSCy Schubert evsig_free_globals_(void)
4692b15cb3dSCy Schubert {
4702b15cb3dSCy Schubert 	evsig_free_globals_locks();
4712b15cb3dSCy Schubert }
4722b15cb3dSCy Schubert 
4732b15cb3dSCy Schubert #ifndef EVENT__DISABLE_THREAD_SUPPORT
4742b15cb3dSCy Schubert int
evsig_global_setup_locks_(const int enable_locks)4752b15cb3dSCy Schubert evsig_global_setup_locks_(const int enable_locks)
4762b15cb3dSCy Schubert {
4772b15cb3dSCy Schubert 	EVTHREAD_SETUP_GLOBAL_LOCK(evsig_base_lock, 0);
4782b15cb3dSCy Schubert 	return 0;
4792b15cb3dSCy Schubert }
4802b15cb3dSCy Schubert 
4812b15cb3dSCy Schubert #endif
482