xref: /netbsd-src/external/bsd/libevent/dist/signal.c (revision 657871a79c9a2060a6255a242fa1a1ef76b56ec6)
1*657871a7Schristos /*	$NetBSD: signal.c,v 1.1.1.4 2021/04/07 02:43:13 christos Exp $	*/
26448a78cSplunky /*	$OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $	*/
36448a78cSplunky 
46448a78cSplunky /*
56ecf6635Schristos  * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu>
66ecf6635Schristos  * Copyright 2007-2012 Niels Provos and Nick Mathewson
76448a78cSplunky  *
86448a78cSplunky  * Redistribution and use in source and binary forms, with or without
96448a78cSplunky  * modification, are permitted provided that the following conditions
106448a78cSplunky  * are met:
116448a78cSplunky  * 1. Redistributions of source code must retain the above copyright
126448a78cSplunky  *    notice, this list of conditions and the following disclaimer.
136448a78cSplunky  * 2. Redistributions in binary form must reproduce the above copyright
146448a78cSplunky  *    notice, this list of conditions and the following disclaimer in the
156448a78cSplunky  *    documentation and/or other materials provided with the distribution.
166448a78cSplunky  * 3. The name of the author may not be used to endorse or promote products
176448a78cSplunky  *    derived from this software without specific prior written permission.
186448a78cSplunky  *
196448a78cSplunky  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
206448a78cSplunky  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
216448a78cSplunky  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
226448a78cSplunky  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
236448a78cSplunky  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
246448a78cSplunky  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
256448a78cSplunky  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
266448a78cSplunky  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
276448a78cSplunky  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
286448a78cSplunky  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
296448a78cSplunky  */
306ecf6635Schristos #include "event2/event-config.h"
316ecf6635Schristos #include <sys/cdefs.h>
32*657871a7Schristos __RCSID("$NetBSD: signal.c,v 1.1.1.4 2021/04/07 02:43:13 christos Exp $");
33805a1ce9Schristos #include "evconfig-private.h"
346448a78cSplunky 
35805a1ce9Schristos #ifdef _WIN32
366448a78cSplunky #define WIN32_LEAN_AND_MEAN
376448a78cSplunky #include <winsock2.h>
386448a78cSplunky #include <windows.h>
396448a78cSplunky #undef WIN32_LEAN_AND_MEAN
406448a78cSplunky #endif
416448a78cSplunky #include <sys/types.h>
42805a1ce9Schristos #ifdef EVENT__HAVE_SYS_TIME_H
436448a78cSplunky #include <sys/time.h>
446448a78cSplunky #endif
456448a78cSplunky #include <sys/queue.h>
46805a1ce9Schristos #ifdef EVENT__HAVE_SYS_SOCKET_H
476448a78cSplunky #include <sys/socket.h>
486448a78cSplunky #endif
496448a78cSplunky #include <signal.h>
506448a78cSplunky #include <stdio.h>
516448a78cSplunky #include <stdlib.h>
526448a78cSplunky #include <string.h>
53805a1ce9Schristos #ifdef EVENT__HAVE_UNISTD_H
546448a78cSplunky #include <unistd.h>
556448a78cSplunky #endif
566448a78cSplunky #include <errno.h>
57805a1ce9Schristos #ifdef EVENT__HAVE_FCNTL_H
586448a78cSplunky #include <fcntl.h>
596448a78cSplunky #endif
606448a78cSplunky 
616ecf6635Schristos #include "event2/event.h"
626ecf6635Schristos #include "event2/event_struct.h"
636448a78cSplunky #include "event-internal.h"
646ecf6635Schristos #include "event2/util.h"
656ecf6635Schristos #include "evsignal-internal.h"
666ecf6635Schristos #include "log-internal.h"
676ecf6635Schristos #include "evmap-internal.h"
686ecf6635Schristos #include "evthread-internal.h"
696448a78cSplunky 
706ecf6635Schristos /*
716ecf6635Schristos   signal.c
726448a78cSplunky 
736ecf6635Schristos   This is the signal-handling implementation we use for backends that don't
746ecf6635Schristos   have a better way to do signal handling.  It uses sigaction() or signal()
756ecf6635Schristos   to set a signal handler, and a socket pair to tell the event base when
766ecf6635Schristos 
776ecf6635Schristos   Note that I said "the event base" : only one event base can be set up to use
786ecf6635Schristos   this at a time.  For historical reasons and backward compatibility, if you
796ecf6635Schristos   add an event for a signal to event_base A, then add an event for a signal
806ecf6635Schristos   (any signal!) to event_base B, event_base B will get informed about the
816ecf6635Schristos   signal, but event_base A won't.
826ecf6635Schristos 
836ecf6635Schristos   It would be neat to change this behavior in some future version of Libevent.
846ecf6635Schristos   kqueue already does something far more sensible.  We can make all backends
856ecf6635Schristos   on Linux do a reasonable thing using signalfd.
866ecf6635Schristos */
876ecf6635Schristos 
88805a1ce9Schristos #ifndef _WIN32
896ecf6635Schristos /* Windows wants us to call our signal handlers as __cdecl.  Nobody else
906ecf6635Schristos  * expects you to do anything crazy like this. */
91*657871a7Schristos #ifndef __cdecl
926ecf6635Schristos #define __cdecl
936ecf6635Schristos #endif
94*657871a7Schristos #endif
956ecf6635Schristos 
966ecf6635Schristos static int evsig_add(struct event_base *, evutil_socket_t, short, short, void *);
976ecf6635Schristos static int evsig_del(struct event_base *, evutil_socket_t, short, short, void *);
986ecf6635Schristos 
996ecf6635Schristos static const struct eventop evsigops = {
1006ecf6635Schristos 	"signal",
1016ecf6635Schristos 	NULL,
1026ecf6635Schristos 	evsig_add,
1036ecf6635Schristos 	evsig_del,
1046ecf6635Schristos 	NULL,
1056ecf6635Schristos 	NULL,
1066ecf6635Schristos 	0, 0, 0
1076ecf6635Schristos };
1086ecf6635Schristos 
109805a1ce9Schristos #ifndef EVENT__DISABLE_THREAD_SUPPORT
1106ecf6635Schristos /* Lock for evsig_base and evsig_base_n_signals_added fields. */
1116ecf6635Schristos static void *evsig_base_lock = NULL;
1126ecf6635Schristos #endif
1136ecf6635Schristos /* The event base that's currently getting informed about signals. */
1146ecf6635Schristos static struct event_base *evsig_base = NULL;
1156ecf6635Schristos /* A copy of evsig_base->sigev_n_signals_added. */
1166ecf6635Schristos static int evsig_base_n_signals_added = 0;
1176ecf6635Schristos static evutil_socket_t evsig_base_fd = -1;
1186ecf6635Schristos 
1196ecf6635Schristos static void __cdecl evsig_handler(int sig);
1206ecf6635Schristos 
1216ecf6635Schristos #define EVSIGBASE_LOCK() EVLOCK_LOCK(evsig_base_lock, 0)
1226ecf6635Schristos #define EVSIGBASE_UNLOCK() EVLOCK_UNLOCK(evsig_base_lock, 0)
1236ecf6635Schristos 
1246ecf6635Schristos void
evsig_set_base_(struct event_base * base)125805a1ce9Schristos evsig_set_base_(struct event_base *base)
1266ecf6635Schristos {
1276ecf6635Schristos 	EVSIGBASE_LOCK();
1286ecf6635Schristos 	evsig_base = base;
1296ecf6635Schristos 	evsig_base_n_signals_added = base->sig.ev_n_signals_added;
130805a1ce9Schristos 	evsig_base_fd = base->sig.ev_signal_pair[1];
1316ecf6635Schristos 	EVSIGBASE_UNLOCK();
1326ecf6635Schristos }
1336448a78cSplunky 
1346448a78cSplunky /* Callback for when the signal handler write a byte to our signaling socket */
1356448a78cSplunky static void
evsig_cb(evutil_socket_t fd,short what,void * arg)1366ecf6635Schristos evsig_cb(evutil_socket_t fd, short what, void *arg)
1376448a78cSplunky {
1386ecf6635Schristos 	static char signals[1024];
1396ecf6635Schristos 	ev_ssize_t n;
1406ecf6635Schristos 	int i;
1416ecf6635Schristos 	int ncaught[NSIG];
1426ecf6635Schristos 	struct event_base *base;
1436448a78cSplunky 
1446ecf6635Schristos 	base = arg;
1456ecf6635Schristos 
1466ecf6635Schristos 	memset(&ncaught, 0, sizeof(ncaught));
1476ecf6635Schristos 
1486ecf6635Schristos 	while (1) {
149805a1ce9Schristos #ifdef _WIN32
1506448a78cSplunky 		n = recv(fd, signals, sizeof(signals), 0);
151805a1ce9Schristos #else
152805a1ce9Schristos 		n = read(fd, signals, sizeof(signals));
153805a1ce9Schristos #endif
1546ecf6635Schristos 		if (n == -1) {
1556ecf6635Schristos 			int err = evutil_socket_geterror(fd);
1566ecf6635Schristos 			if (! EVUTIL_ERR_RW_RETRIABLE(err))
1576ecf6635Schristos 				event_sock_err(1, fd, "%s: recv", __func__);
1586ecf6635Schristos 			break;
1596ecf6635Schristos 		} else if (n == 0) {
1606ecf6635Schristos 			/* XXX warn? */
1616ecf6635Schristos 			break;
1626ecf6635Schristos 		}
1636ecf6635Schristos 		for (i = 0; i < n; ++i) {
1646ecf6635Schristos 			ev_uint8_t sig = signals[i];
1656ecf6635Schristos 			if (sig < NSIG)
1666ecf6635Schristos 				ncaught[sig]++;
1676ecf6635Schristos 		}
1686448a78cSplunky 	}
1696448a78cSplunky 
1706ecf6635Schristos 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
1716ecf6635Schristos 	for (i = 0; i < NSIG; ++i) {
1726ecf6635Schristos 		if (ncaught[i])
173805a1ce9Schristos 			evmap_signal_active_(base, i, ncaught[i]);
1746ecf6635Schristos 	}
1756ecf6635Schristos 	EVBASE_RELEASE_LOCK(base, th_base_lock);
1766ecf6635Schristos }
1776448a78cSplunky 
1786448a78cSplunky int
evsig_init_(struct event_base * base)179805a1ce9Schristos evsig_init_(struct event_base *base)
1806448a78cSplunky {
1816448a78cSplunky 	/*
1826448a78cSplunky 	 * Our signal handler is going to write to one end of the socket
1836448a78cSplunky 	 * pair to wake up our event loop.  The event loop then scans for
1846448a78cSplunky 	 * signals that got delivered.
1856448a78cSplunky 	 */
186805a1ce9Schristos 	if (evutil_make_internal_pipe_(base->sig.ev_signal_pair) == -1) {
187805a1ce9Schristos #ifdef _WIN32
1886448a78cSplunky 		/* Make this nonfatal on win32, where sometimes people
1896448a78cSplunky 		   have localhost firewalled. */
1906ecf6635Schristos 		event_sock_warn(-1, "%s: socketpair", __func__);
1916448a78cSplunky #else
1926ecf6635Schristos 		event_sock_err(1, -1, "%s: socketpair", __func__);
1936448a78cSplunky #endif
1946448a78cSplunky 		return -1;
1956448a78cSplunky 	}
1966448a78cSplunky 
197805a1ce9Schristos 	if (base->sig.sh_old) {
198805a1ce9Schristos 		mm_free(base->sig.sh_old);
199805a1ce9Schristos 	}
2006448a78cSplunky 	base->sig.sh_old = NULL;
2016448a78cSplunky 	base->sig.sh_old_max = 0;
2026448a78cSplunky 
203805a1ce9Schristos 	event_assign(&base->sig.ev_signal, base, base->sig.ev_signal_pair[0],
2046ecf6635Schristos 		EV_READ | EV_PERSIST, evsig_cb, base);
2056ecf6635Schristos 
2066448a78cSplunky 	base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL;
2076ecf6635Schristos 	event_priority_set(&base->sig.ev_signal, 0);
2086ecf6635Schristos 
2096ecf6635Schristos 	base->evsigsel = &evsigops;
2106448a78cSplunky 
2116448a78cSplunky 	return 0;
2126448a78cSplunky }
2136448a78cSplunky 
2146448a78cSplunky /* Helper: set the signal handler for evsignal to handler in base, so that
2156448a78cSplunky  * we can restore the original handler when we clear the current one. */
2166448a78cSplunky int
evsig_set_handler_(struct event_base * base,int evsignal,void (__cdecl * handler)(int))217805a1ce9Schristos evsig_set_handler_(struct event_base *base,
2186ecf6635Schristos     int evsignal, void (__cdecl *handler)(int))
2196448a78cSplunky {
220805a1ce9Schristos #ifdef EVENT__HAVE_SIGACTION
2216448a78cSplunky 	struct sigaction sa;
2226448a78cSplunky #else
2236448a78cSplunky 	ev_sighandler_t sh;
2246448a78cSplunky #endif
2256ecf6635Schristos 	struct evsig_info *sig = &base->sig;
2266448a78cSplunky 	void *p;
2276448a78cSplunky 
2286448a78cSplunky 	/*
2296448a78cSplunky 	 * resize saved signal handler array up to the highest signal number.
2306448a78cSplunky 	 * a dynamic array is used to keep footprint on the low side.
2316448a78cSplunky 	 */
2326448a78cSplunky 	if (evsignal >= sig->sh_old_max) {
2336448a78cSplunky 		int new_max = evsignal + 1;
2346448a78cSplunky 		event_debug(("%s: evsignal (%d) >= sh_old_max (%d), resizing",
2356448a78cSplunky 			    __func__, evsignal, sig->sh_old_max));
2366ecf6635Schristos 		p = mm_realloc(sig->sh_old, new_max * sizeof(*sig->sh_old));
2376448a78cSplunky 		if (p == NULL) {
2386448a78cSplunky 			event_warn("realloc");
2396448a78cSplunky 			return (-1);
2406448a78cSplunky 		}
2416448a78cSplunky 
2426448a78cSplunky 		memset((char *)p + sig->sh_old_max * sizeof(*sig->sh_old),
2436448a78cSplunky 		    0, (new_max - sig->sh_old_max) * sizeof(*sig->sh_old));
2446448a78cSplunky 
2456448a78cSplunky 		sig->sh_old_max = new_max;
2466448a78cSplunky 		sig->sh_old = p;
2476448a78cSplunky 	}
2486448a78cSplunky 
2496448a78cSplunky 	/* allocate space for previous handler out of dynamic array */
2506ecf6635Schristos 	sig->sh_old[evsignal] = mm_malloc(sizeof *sig->sh_old[evsignal]);
2516448a78cSplunky 	if (sig->sh_old[evsignal] == NULL) {
2526448a78cSplunky 		event_warn("malloc");
2536448a78cSplunky 		return (-1);
2546448a78cSplunky 	}
2556448a78cSplunky 
2566448a78cSplunky 	/* save previous handler and setup new handler */
257805a1ce9Schristos #ifdef EVENT__HAVE_SIGACTION
2586448a78cSplunky 	memset(&sa, 0, sizeof(sa));
2596448a78cSplunky 	sa.sa_handler = handler;
2606448a78cSplunky 	sa.sa_flags |= SA_RESTART;
2616448a78cSplunky 	sigfillset(&sa.sa_mask);
2626448a78cSplunky 
2636448a78cSplunky 	if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) {
2646448a78cSplunky 		event_warn("sigaction");
2656ecf6635Schristos 		mm_free(sig->sh_old[evsignal]);
2666ecf6635Schristos 		sig->sh_old[evsignal] = NULL;
2676448a78cSplunky 		return (-1);
2686448a78cSplunky 	}
2696448a78cSplunky #else
2706448a78cSplunky 	if ((sh = signal(evsignal, handler)) == SIG_ERR) {
2716448a78cSplunky 		event_warn("signal");
2726ecf6635Schristos 		mm_free(sig->sh_old[evsignal]);
2736ecf6635Schristos 		sig->sh_old[evsignal] = NULL;
2746448a78cSplunky 		return (-1);
2756448a78cSplunky 	}
2766448a78cSplunky 	*sig->sh_old[evsignal] = sh;
2776448a78cSplunky #endif
2786448a78cSplunky 
2796448a78cSplunky 	return (0);
2806448a78cSplunky }
2816448a78cSplunky 
2826ecf6635Schristos static int
evsig_add(struct event_base * base,evutil_socket_t evsignal,short old,short events,void * p)2836ecf6635Schristos evsig_add(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p)
2846448a78cSplunky {
2856ecf6635Schristos 	struct evsig_info *sig = &base->sig;
2866ecf6635Schristos 	(void)p;
2876448a78cSplunky 
2886ecf6635Schristos 	EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG);
2896448a78cSplunky 
2906448a78cSplunky 	/* catch signals if they happen quickly */
2916ecf6635Schristos 	EVSIGBASE_LOCK();
2926ecf6635Schristos 	if (evsig_base != base && evsig_base_n_signals_added) {
2936ecf6635Schristos 		event_warnx("Added a signal to event base %p with signals "
2946ecf6635Schristos 		    "already added to event_base %p.  Only one can have "
2956ecf6635Schristos 		    "signals at a time with the %s backend.  The base with "
2966ecf6635Schristos 		    "the most recently added signal or the most recent "
2976ecf6635Schristos 		    "event_base_loop() call gets preference; do "
2986ecf6635Schristos 		    "not rely on this behavior in future Libevent versions.",
2996ecf6635Schristos 		    base, evsig_base, base->evsel->name);
3006ecf6635Schristos 	}
3016ecf6635Schristos 	evsig_base = base;
3026ecf6635Schristos 	evsig_base_n_signals_added = ++sig->ev_n_signals_added;
303805a1ce9Schristos 	evsig_base_fd = base->sig.ev_signal_pair[1];
3046ecf6635Schristos 	EVSIGBASE_UNLOCK();
3056ecf6635Schristos 
3066ecf6635Schristos 	event_debug(("%s: %d: changing signal handler", __func__, (int)evsignal));
307805a1ce9Schristos 	if (evsig_set_handler_(base, (int)evsignal, evsig_handler) == -1) {
3086ecf6635Schristos 		goto err;
3096ecf6635Schristos 	}
3106ecf6635Schristos 
3116448a78cSplunky 
3126448a78cSplunky 	if (!sig->ev_signal_added) {
313805a1ce9Schristos 		if (event_add_nolock_(&sig->ev_signal, NULL, 0))
3146ecf6635Schristos 			goto err;
3156448a78cSplunky 		sig->ev_signal_added = 1;
3166448a78cSplunky 	}
3176448a78cSplunky 
3186448a78cSplunky 	return (0);
3196ecf6635Schristos 
3206ecf6635Schristos err:
3216ecf6635Schristos 	EVSIGBASE_LOCK();
3226ecf6635Schristos 	--evsig_base_n_signals_added;
3236ecf6635Schristos 	--sig->ev_n_signals_added;
3246ecf6635Schristos 	EVSIGBASE_UNLOCK();
3256ecf6635Schristos 	return (-1);
3266448a78cSplunky }
3276448a78cSplunky 
3286448a78cSplunky int
evsig_restore_handler_(struct event_base * base,int evsignal)329805a1ce9Schristos evsig_restore_handler_(struct event_base *base, int evsignal)
3306448a78cSplunky {
3316448a78cSplunky 	int ret = 0;
3326ecf6635Schristos 	struct evsig_info *sig = &base->sig;
333805a1ce9Schristos #ifdef EVENT__HAVE_SIGACTION
3346448a78cSplunky 	struct sigaction *sh;
3356448a78cSplunky #else
3366448a78cSplunky 	ev_sighandler_t *sh;
3376448a78cSplunky #endif
3386448a78cSplunky 
339805a1ce9Schristos 	if (evsignal >= sig->sh_old_max) {
340805a1ce9Schristos 		/* Can't actually restore. */
341805a1ce9Schristos 		/* XXXX.*/
342805a1ce9Schristos 		return 0;
343805a1ce9Schristos 	}
344805a1ce9Schristos 
3456448a78cSplunky 	/* restore previous handler */
3466448a78cSplunky 	sh = sig->sh_old[evsignal];
3476448a78cSplunky 	sig->sh_old[evsignal] = NULL;
348805a1ce9Schristos #ifdef EVENT__HAVE_SIGACTION
3496448a78cSplunky 	if (sigaction(evsignal, sh, NULL) == -1) {
3506448a78cSplunky 		event_warn("sigaction");
3516448a78cSplunky 		ret = -1;
3526448a78cSplunky 	}
3536448a78cSplunky #else
3546448a78cSplunky 	if (signal(evsignal, *sh) == SIG_ERR) {
3556448a78cSplunky 		event_warn("signal");
3566448a78cSplunky 		ret = -1;
3576448a78cSplunky 	}
3586448a78cSplunky #endif
3596ecf6635Schristos 
3606ecf6635Schristos 	mm_free(sh);
3616448a78cSplunky 
3626448a78cSplunky 	return ret;
3636448a78cSplunky }
3646448a78cSplunky 
3656ecf6635Schristos static int
evsig_del(struct event_base * base,evutil_socket_t evsignal,short old,short events,void * p)3666ecf6635Schristos evsig_del(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p)
3676448a78cSplunky {
3686ecf6635Schristos 	EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG);
3696448a78cSplunky 
3706ecf6635Schristos 	event_debug(("%s: "EV_SOCK_FMT": restoring signal handler",
3716ecf6635Schristos 		__func__, EV_SOCK_ARG(evsignal)));
3726448a78cSplunky 
3736ecf6635Schristos 	EVSIGBASE_LOCK();
3746ecf6635Schristos 	--evsig_base_n_signals_added;
3756ecf6635Schristos 	--base->sig.ev_n_signals_added;
3766ecf6635Schristos 	EVSIGBASE_UNLOCK();
3776448a78cSplunky 
378805a1ce9Schristos 	return (evsig_restore_handler_(base, (int)evsignal));
3796448a78cSplunky }
3806448a78cSplunky 
3816ecf6635Schristos static void __cdecl
evsig_handler(int sig)3826ecf6635Schristos evsig_handler(int sig)
3836448a78cSplunky {
3846448a78cSplunky 	int save_errno = errno;
385805a1ce9Schristos #ifdef _WIN32
3866ecf6635Schristos 	int socket_errno = EVUTIL_SOCKET_ERROR();
3876ecf6635Schristos #endif
3886ecf6635Schristos 	ev_uint8_t msg;
3896448a78cSplunky 
3906ecf6635Schristos 	if (evsig_base == NULL) {
3916ecf6635Schristos 		event_warnx(
3926448a78cSplunky 			"%s: received signal %d, but have no base configured",
3936448a78cSplunky 			__func__, sig);
3946448a78cSplunky 		return;
3956448a78cSplunky 	}
3966448a78cSplunky 
397805a1ce9Schristos #ifndef EVENT__HAVE_SIGACTION
3986ecf6635Schristos 	signal(sig, evsig_handler);
3996448a78cSplunky #endif
4006448a78cSplunky 
4016448a78cSplunky 	/* Wake up our notification mechanism */
4026ecf6635Schristos 	msg = sig;
403805a1ce9Schristos #ifdef _WIN32
4046ecf6635Schristos 	send(evsig_base_fd, (char*)&msg, 1, 0);
405805a1ce9Schristos #else
406805a1ce9Schristos 	{
407805a1ce9Schristos 		int r = write(evsig_base_fd, (char*)&msg, 1);
408805a1ce9Schristos 		(void)r; /* Suppress 'unused return value' and 'unused var' */
409805a1ce9Schristos 	}
410805a1ce9Schristos #endif
4116448a78cSplunky 	errno = save_errno;
412805a1ce9Schristos #ifdef _WIN32
4136ecf6635Schristos 	EVUTIL_SET_SOCKET_ERROR(socket_errno);
4146ecf6635Schristos #endif
4156448a78cSplunky }
4166448a78cSplunky 
4176448a78cSplunky void
evsig_dealloc_(struct event_base * base)418805a1ce9Schristos evsig_dealloc_(struct event_base *base)
4196448a78cSplunky {
4206448a78cSplunky 	int i = 0;
4216448a78cSplunky 	if (base->sig.ev_signal_added) {
4226448a78cSplunky 		event_del(&base->sig.ev_signal);
4236448a78cSplunky 		base->sig.ev_signal_added = 0;
4246448a78cSplunky 	}
425805a1ce9Schristos 	/* debug event is created in evsig_init_/event_assign even when
4266ecf6635Schristos 	 * ev_signal_added == 0, so unassign is required */
4276ecf6635Schristos 	event_debug_unassign(&base->sig.ev_signal);
4286ecf6635Schristos 
4296448a78cSplunky 	for (i = 0; i < NSIG; ++i) {
4306448a78cSplunky 		if (i < base->sig.sh_old_max && base->sig.sh_old[i] != NULL)
431805a1ce9Schristos 			evsig_restore_handler_(base, i);
4326448a78cSplunky 	}
4336ecf6635Schristos 	EVSIGBASE_LOCK();
4346ecf6635Schristos 	if (base == evsig_base) {
4356ecf6635Schristos 		evsig_base = NULL;
4366ecf6635Schristos 		evsig_base_n_signals_added = 0;
4376ecf6635Schristos 		evsig_base_fd = -1;
4386ecf6635Schristos 	}
4396ecf6635Schristos 	EVSIGBASE_UNLOCK();
4406448a78cSplunky 
4416ecf6635Schristos 	if (base->sig.ev_signal_pair[0] != -1) {
4426ecf6635Schristos 		evutil_closesocket(base->sig.ev_signal_pair[0]);
4436448a78cSplunky 		base->sig.ev_signal_pair[0] = -1;
4446ecf6635Schristos 	}
4456ecf6635Schristos 	if (base->sig.ev_signal_pair[1] != -1) {
4466ecf6635Schristos 		evutil_closesocket(base->sig.ev_signal_pair[1]);
4476448a78cSplunky 		base->sig.ev_signal_pair[1] = -1;
4486ecf6635Schristos 	}
4496448a78cSplunky 	base->sig.sh_old_max = 0;
4506448a78cSplunky 
4516ecf6635Schristos 	/* per index frees are handled in evsig_del() */
4526ecf6635Schristos 	if (base->sig.sh_old) {
4536ecf6635Schristos 		mm_free(base->sig.sh_old);
4546ecf6635Schristos 		base->sig.sh_old = NULL;
4556448a78cSplunky 	}
4566ecf6635Schristos }
4576ecf6635Schristos 
458805a1ce9Schristos static void
evsig_free_globals_locks(void)459805a1ce9Schristos evsig_free_globals_locks(void)
460805a1ce9Schristos {
461805a1ce9Schristos #ifndef EVENT__DISABLE_THREAD_SUPPORT
462805a1ce9Schristos 	if (evsig_base_lock != NULL) {
463805a1ce9Schristos 		EVTHREAD_FREE_LOCK(evsig_base_lock, 0);
464805a1ce9Schristos 		evsig_base_lock = NULL;
465805a1ce9Schristos 	}
466805a1ce9Schristos #endif
467805a1ce9Schristos 	return;
468805a1ce9Schristos }
469805a1ce9Schristos 
470805a1ce9Schristos void
evsig_free_globals_(void)471805a1ce9Schristos evsig_free_globals_(void)
472805a1ce9Schristos {
473805a1ce9Schristos 	evsig_free_globals_locks();
474805a1ce9Schristos }
475805a1ce9Schristos 
476805a1ce9Schristos #ifndef EVENT__DISABLE_THREAD_SUPPORT
4776ecf6635Schristos int
evsig_global_setup_locks_(const int enable_locks)4786ecf6635Schristos evsig_global_setup_locks_(const int enable_locks)
4796ecf6635Schristos {
4806ecf6635Schristos 	EVTHREAD_SETUP_GLOBAL_LOCK(evsig_base_lock, 0);
4816ecf6635Schristos 	return 0;
4826ecf6635Schristos }
483805a1ce9Schristos 
4846ecf6635Schristos #endif
485