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