1*eabc0478Schristos /* $NetBSD: signal.c,v 1.6 2024/08/18 20:47:21 christos Exp $ */ 28585484eSchristos 38585484eSchristos /* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ 48585484eSchristos 58585484eSchristos /* 68585484eSchristos * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu> 78585484eSchristos * Copyright 2007-2012 Niels Provos and Nick Mathewson 88585484eSchristos * 98585484eSchristos * Redistribution and use in source and binary forms, with or without 108585484eSchristos * modification, are permitted provided that the following conditions 118585484eSchristos * are met: 128585484eSchristos * 1. Redistributions of source code must retain the above copyright 138585484eSchristos * notice, this list of conditions and the following disclaimer. 148585484eSchristos * 2. Redistributions in binary form must reproduce the above copyright 158585484eSchristos * notice, this list of conditions and the following disclaimer in the 168585484eSchristos * documentation and/or other materials provided with the distribution. 178585484eSchristos * 3. The name of the author may not be used to endorse or promote products 188585484eSchristos * derived from this software without specific prior written permission. 198585484eSchristos * 208585484eSchristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 218585484eSchristos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 228585484eSchristos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 238585484eSchristos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 248585484eSchristos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 258585484eSchristos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 268585484eSchristos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 278585484eSchristos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 288585484eSchristos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 298585484eSchristos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 308585484eSchristos */ 318585484eSchristos #include "event2/event-config.h" 328585484eSchristos #include "evconfig-private.h" 338585484eSchristos 348585484eSchristos #ifdef _WIN32 358585484eSchristos #define WIN32_LEAN_AND_MEAN 368585484eSchristos #include <winsock2.h> 378585484eSchristos #include <windows.h> 388585484eSchristos #undef WIN32_LEAN_AND_MEAN 398585484eSchristos #endif 408585484eSchristos #include <sys/types.h> 418585484eSchristos #ifdef EVENT__HAVE_SYS_TIME_H 428585484eSchristos #include <sys/time.h> 438585484eSchristos #endif 448585484eSchristos #include <sys/queue.h> 458585484eSchristos #ifdef EVENT__HAVE_SYS_SOCKET_H 468585484eSchristos #include <sys/socket.h> 478585484eSchristos #endif 488585484eSchristos #include <signal.h> 498585484eSchristos #include <stdio.h> 508585484eSchristos #include <stdlib.h> 518585484eSchristos #include <string.h> 528585484eSchristos #ifdef EVENT__HAVE_UNISTD_H 538585484eSchristos #include <unistd.h> 548585484eSchristos #endif 558585484eSchristos #include <errno.h> 568585484eSchristos #ifdef EVENT__HAVE_FCNTL_H 578585484eSchristos #include <fcntl.h> 588585484eSchristos #endif 598585484eSchristos 608585484eSchristos #include "event2/event.h" 618585484eSchristos #include "event2/event_struct.h" 628585484eSchristos #include "event-internal.h" 638585484eSchristos #include "event2/util.h" 648585484eSchristos #include "evsignal-internal.h" 658585484eSchristos #include "log-internal.h" 668585484eSchristos #include "evmap-internal.h" 678585484eSchristos #include "evthread-internal.h" 688585484eSchristos 698585484eSchristos /* 708585484eSchristos signal.c 718585484eSchristos 728585484eSchristos This is the signal-handling implementation we use for backends that don't 738585484eSchristos have a better way to do signal handling. It uses sigaction() or signal() 748585484eSchristos to set a signal handler, and a socket pair to tell the event base when 758585484eSchristos 768585484eSchristos Note that I said "the event base" : only one event base can be set up to use 778585484eSchristos this at a time. For historical reasons and backward compatibility, if you 788585484eSchristos add an event for a signal to event_base A, then add an event for a signal 798585484eSchristos (any signal!) to event_base B, event_base B will get informed about the 808585484eSchristos signal, but event_base A won't. 818585484eSchristos 828585484eSchristos It would be neat to change this behavior in some future version of Libevent. 838585484eSchristos kqueue already does something far more sensible. We can make all backends 848585484eSchristos on Linux do a reasonable thing using signalfd. 858585484eSchristos */ 868585484eSchristos 878585484eSchristos #ifndef _WIN32 888585484eSchristos /* Windows wants us to call our signal handlers as __cdecl. Nobody else 898585484eSchristos * expects you to do anything crazy like this. */ 90*eabc0478Schristos #ifndef __cdecl 918585484eSchristos #define __cdecl 928585484eSchristos #endif 93*eabc0478Schristos #endif 948585484eSchristos 958585484eSchristos static int evsig_add(struct event_base *, evutil_socket_t, short, short, void *); 968585484eSchristos static int evsig_del(struct event_base *, evutil_socket_t, short, short, void *); 978585484eSchristos 988585484eSchristos static const struct eventop evsigops = { 998585484eSchristos "signal", 1008585484eSchristos NULL, 1018585484eSchristos evsig_add, 1028585484eSchristos evsig_del, 1038585484eSchristos NULL, 1048585484eSchristos NULL, 1058585484eSchristos 0, 0, 0 1068585484eSchristos }; 1078585484eSchristos 1088585484eSchristos #ifndef EVENT__DISABLE_THREAD_SUPPORT 1098585484eSchristos /* Lock for evsig_base and evsig_base_n_signals_added fields. */ 1108585484eSchristos static void *evsig_base_lock = NULL; 1118585484eSchristos #endif 1128585484eSchristos /* The event base that's currently getting informed about signals. */ 1138585484eSchristos static struct event_base *evsig_base = NULL; 1148585484eSchristos /* A copy of evsig_base->sigev_n_signals_added. */ 1158585484eSchristos static int evsig_base_n_signals_added = 0; 1168585484eSchristos static evutil_socket_t evsig_base_fd = -1; 1178585484eSchristos 1188585484eSchristos static void __cdecl evsig_handler(int sig); 1198585484eSchristos 1208585484eSchristos #define EVSIGBASE_LOCK() EVLOCK_LOCK(evsig_base_lock, 0) 1218585484eSchristos #define EVSIGBASE_UNLOCK() EVLOCK_UNLOCK(evsig_base_lock, 0) 1228585484eSchristos 1238585484eSchristos void 1248585484eSchristos evsig_set_base_(struct event_base *base) 1258585484eSchristos { 1268585484eSchristos EVSIGBASE_LOCK(); 1278585484eSchristos evsig_base = base; 1288585484eSchristos evsig_base_n_signals_added = base->sig.ev_n_signals_added; 1298585484eSchristos evsig_base_fd = base->sig.ev_signal_pair[1]; 1308585484eSchristos EVSIGBASE_UNLOCK(); 1318585484eSchristos } 1328585484eSchristos 1338585484eSchristos /* Callback for when the signal handler write a byte to our signaling socket */ 1348585484eSchristos static void 1358585484eSchristos evsig_cb(evutil_socket_t fd, short what, void *arg) 1368585484eSchristos { 1378585484eSchristos static char signals[1024]; 1388585484eSchristos ev_ssize_t n; 1398585484eSchristos int i; 1408585484eSchristos int ncaught[NSIG]; 1418585484eSchristos struct event_base *base; 1428585484eSchristos 1438585484eSchristos base = arg; 1448585484eSchristos 1458585484eSchristos memset(&ncaught, 0, sizeof(ncaught)); 1468585484eSchristos 1478585484eSchristos while (1) { 1488585484eSchristos #ifdef _WIN32 1498585484eSchristos n = recv(fd, signals, sizeof(signals), 0); 1508585484eSchristos #else 1518585484eSchristos n = read(fd, signals, sizeof(signals)); 1528585484eSchristos #endif 1538585484eSchristos if (n == -1) { 1548585484eSchristos int err = evutil_socket_geterror(fd); 1558585484eSchristos if (! EVUTIL_ERR_RW_RETRIABLE(err)) 1568585484eSchristos event_sock_err(1, fd, "%s: recv", __func__); 1578585484eSchristos break; 1588585484eSchristos } else if (n == 0) { 1598585484eSchristos /* XXX warn? */ 1608585484eSchristos break; 1618585484eSchristos } 1628585484eSchristos for (i = 0; i < n; ++i) { 1638585484eSchristos ev_uint8_t sig = signals[i]; 1648585484eSchristos if (sig < NSIG) 1658585484eSchristos ncaught[sig]++; 1668585484eSchristos } 1678585484eSchristos } 1688585484eSchristos 1698585484eSchristos EVBASE_ACQUIRE_LOCK(base, th_base_lock); 1708585484eSchristos for (i = 0; i < NSIG; ++i) { 1718585484eSchristos if (ncaught[i]) 1728585484eSchristos evmap_signal_active_(base, i, ncaught[i]); 1738585484eSchristos } 1748585484eSchristos EVBASE_RELEASE_LOCK(base, th_base_lock); 1758585484eSchristos } 1768585484eSchristos 1778585484eSchristos int 1788585484eSchristos evsig_init_(struct event_base *base) 1798585484eSchristos { 1808585484eSchristos /* 1818585484eSchristos * Our signal handler is going to write to one end of the socket 1828585484eSchristos * pair to wake up our event loop. The event loop then scans for 1838585484eSchristos * signals that got delivered. 1848585484eSchristos */ 1858585484eSchristos if (evutil_make_internal_pipe_(base->sig.ev_signal_pair) == -1) { 1868585484eSchristos #ifdef _WIN32 1878585484eSchristos /* Make this nonfatal on win32, where sometimes people 1888585484eSchristos have localhost firewalled. */ 1898585484eSchristos event_sock_warn(-1, "%s: socketpair", __func__); 1908585484eSchristos #else 1918585484eSchristos event_sock_err(1, -1, "%s: socketpair", __func__); 1928585484eSchristos #endif 1938585484eSchristos return -1; 1948585484eSchristos } 1958585484eSchristos 1968585484eSchristos if (base->sig.sh_old) { 1978585484eSchristos mm_free(base->sig.sh_old); 1988585484eSchristos } 1998585484eSchristos base->sig.sh_old = NULL; 2008585484eSchristos base->sig.sh_old_max = 0; 2018585484eSchristos 2028585484eSchristos event_assign(&base->sig.ev_signal, base, base->sig.ev_signal_pair[0], 2038585484eSchristos EV_READ | EV_PERSIST, evsig_cb, base); 2048585484eSchristos 2058585484eSchristos base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL; 2068585484eSchristos event_priority_set(&base->sig.ev_signal, 0); 2078585484eSchristos 2088585484eSchristos base->evsigsel = &evsigops; 2098585484eSchristos 2108585484eSchristos return 0; 2118585484eSchristos } 2128585484eSchristos 2138585484eSchristos /* Helper: set the signal handler for evsignal to handler in base, so that 2148585484eSchristos * we can restore the original handler when we clear the current one. */ 2158585484eSchristos int 2168585484eSchristos evsig_set_handler_(struct event_base *base, 2178585484eSchristos int evsignal, void (__cdecl *handler)(int)) 2188585484eSchristos { 2198585484eSchristos #ifdef EVENT__HAVE_SIGACTION 2208585484eSchristos struct sigaction sa; 2218585484eSchristos #else 2228585484eSchristos ev_sighandler_t sh; 2238585484eSchristos #endif 2248585484eSchristos struct evsig_info *sig = &base->sig; 2258585484eSchristos void *p; 2268585484eSchristos 2278585484eSchristos /* 2288585484eSchristos * resize saved signal handler array up to the highest signal number. 2298585484eSchristos * a dynamic array is used to keep footprint on the low side. 2308585484eSchristos */ 2318585484eSchristos if (evsignal >= sig->sh_old_max) { 2328585484eSchristos int new_max = evsignal + 1; 2338585484eSchristos event_debug(("%s: evsignal (%d) >= sh_old_max (%d), resizing", 2348585484eSchristos __func__, evsignal, sig->sh_old_max)); 2358585484eSchristos p = mm_realloc(sig->sh_old, new_max * sizeof(*sig->sh_old)); 2368585484eSchristos if (p == NULL) { 2378585484eSchristos event_warn("realloc"); 2388585484eSchristos return (-1); 2398585484eSchristos } 2408585484eSchristos 2418585484eSchristos memset((char *)p + sig->sh_old_max * sizeof(*sig->sh_old), 2428585484eSchristos 0, (new_max - sig->sh_old_max) * sizeof(*sig->sh_old)); 2438585484eSchristos 2448585484eSchristos sig->sh_old_max = new_max; 2458585484eSchristos sig->sh_old = p; 2468585484eSchristos } 2478585484eSchristos 2488585484eSchristos /* allocate space for previous handler out of dynamic array */ 2498585484eSchristos sig->sh_old[evsignal] = mm_malloc(sizeof *sig->sh_old[evsignal]); 2508585484eSchristos if (sig->sh_old[evsignal] == NULL) { 2518585484eSchristos event_warn("malloc"); 2528585484eSchristos return (-1); 2538585484eSchristos } 2548585484eSchristos 2558585484eSchristos /* save previous handler and setup new handler */ 2568585484eSchristos #ifdef EVENT__HAVE_SIGACTION 2578585484eSchristos memset(&sa, 0, sizeof(sa)); 2588585484eSchristos sa.sa_handler = handler; 2598585484eSchristos sa.sa_flags |= SA_RESTART; 2608585484eSchristos sigfillset(&sa.sa_mask); 2618585484eSchristos 2628585484eSchristos if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) { 2638585484eSchristos event_warn("sigaction"); 2648585484eSchristos mm_free(sig->sh_old[evsignal]); 2658585484eSchristos sig->sh_old[evsignal] = NULL; 2668585484eSchristos return (-1); 2678585484eSchristos } 2688585484eSchristos #else 2698585484eSchristos if ((sh = signal(evsignal, handler)) == SIG_ERR) { 2708585484eSchristos event_warn("signal"); 2718585484eSchristos mm_free(sig->sh_old[evsignal]); 2728585484eSchristos sig->sh_old[evsignal] = NULL; 2738585484eSchristos return (-1); 2748585484eSchristos } 2758585484eSchristos *sig->sh_old[evsignal] = sh; 2768585484eSchristos #endif 2778585484eSchristos 2788585484eSchristos return (0); 2798585484eSchristos } 2808585484eSchristos 2818585484eSchristos static int 2828585484eSchristos evsig_add(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p) 2838585484eSchristos { 2848585484eSchristos struct evsig_info *sig = &base->sig; 2858585484eSchristos (void)p; 2868585484eSchristos 2878585484eSchristos EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG); 2888585484eSchristos 2898585484eSchristos /* catch signals if they happen quickly */ 2908585484eSchristos EVSIGBASE_LOCK(); 2918585484eSchristos if (evsig_base != base && evsig_base_n_signals_added) { 2928585484eSchristos event_warnx("Added a signal to event base %p with signals " 2938585484eSchristos "already added to event_base %p. Only one can have " 2948585484eSchristos "signals at a time with the %s backend. The base with " 2958585484eSchristos "the most recently added signal or the most recent " 2968585484eSchristos "event_base_loop() call gets preference; do " 2978585484eSchristos "not rely on this behavior in future Libevent versions.", 2988585484eSchristos base, evsig_base, base->evsel->name); 2998585484eSchristos } 3008585484eSchristos evsig_base = base; 3018585484eSchristos evsig_base_n_signals_added = ++sig->ev_n_signals_added; 3028585484eSchristos evsig_base_fd = base->sig.ev_signal_pair[1]; 3038585484eSchristos EVSIGBASE_UNLOCK(); 3048585484eSchristos 3058585484eSchristos event_debug(("%s: %d: changing signal handler", __func__, (int)evsignal)); 3068585484eSchristos if (evsig_set_handler_(base, (int)evsignal, evsig_handler) == -1) { 3078585484eSchristos goto err; 3088585484eSchristos } 3098585484eSchristos 3108585484eSchristos 3118585484eSchristos if (!sig->ev_signal_added) { 3128585484eSchristos if (event_add_nolock_(&sig->ev_signal, NULL, 0)) 3138585484eSchristos goto err; 3148585484eSchristos sig->ev_signal_added = 1; 3158585484eSchristos } 3168585484eSchristos 3178585484eSchristos return (0); 3188585484eSchristos 3198585484eSchristos err: 3208585484eSchristos EVSIGBASE_LOCK(); 3218585484eSchristos --evsig_base_n_signals_added; 3228585484eSchristos --sig->ev_n_signals_added; 3238585484eSchristos EVSIGBASE_UNLOCK(); 3248585484eSchristos return (-1); 3258585484eSchristos } 3268585484eSchristos 3278585484eSchristos int 3288585484eSchristos evsig_restore_handler_(struct event_base *base, int evsignal) 3298585484eSchristos { 3308585484eSchristos int ret = 0; 3318585484eSchristos struct evsig_info *sig = &base->sig; 3328585484eSchristos #ifdef EVENT__HAVE_SIGACTION 3338585484eSchristos struct sigaction *sh; 3348585484eSchristos #else 3358585484eSchristos ev_sighandler_t *sh; 3368585484eSchristos #endif 3378585484eSchristos 3388585484eSchristos if (evsignal >= sig->sh_old_max) { 3398585484eSchristos /* Can't actually restore. */ 3408585484eSchristos /* XXXX.*/ 3418585484eSchristos return 0; 3428585484eSchristos } 3438585484eSchristos 3448585484eSchristos /* restore previous handler */ 3458585484eSchristos sh = sig->sh_old[evsignal]; 3468585484eSchristos sig->sh_old[evsignal] = NULL; 3478585484eSchristos #ifdef EVENT__HAVE_SIGACTION 3488585484eSchristos if (sigaction(evsignal, sh, NULL) == -1) { 3498585484eSchristos event_warn("sigaction"); 3508585484eSchristos ret = -1; 3518585484eSchristos } 3528585484eSchristos #else 3538585484eSchristos if (signal(evsignal, *sh) == SIG_ERR) { 3548585484eSchristos event_warn("signal"); 3558585484eSchristos ret = -1; 3568585484eSchristos } 3578585484eSchristos #endif 3588585484eSchristos 3598585484eSchristos mm_free(sh); 3608585484eSchristos 3618585484eSchristos return ret; 3628585484eSchristos } 3638585484eSchristos 3648585484eSchristos static int 3658585484eSchristos evsig_del(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p) 3668585484eSchristos { 3678585484eSchristos EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG); 3688585484eSchristos 3698585484eSchristos event_debug(("%s: "EV_SOCK_FMT": restoring signal handler", 3708585484eSchristos __func__, EV_SOCK_ARG(evsignal))); 3718585484eSchristos 3728585484eSchristos EVSIGBASE_LOCK(); 3738585484eSchristos --evsig_base_n_signals_added; 3748585484eSchristos --base->sig.ev_n_signals_added; 3758585484eSchristos EVSIGBASE_UNLOCK(); 3768585484eSchristos 3778585484eSchristos return (evsig_restore_handler_(base, (int)evsignal)); 3788585484eSchristos } 3798585484eSchristos 3808585484eSchristos static void __cdecl 3818585484eSchristos evsig_handler(int sig) 3828585484eSchristos { 3838585484eSchristos int save_errno = errno; 3848585484eSchristos #ifdef _WIN32 3858585484eSchristos int socket_errno = EVUTIL_SOCKET_ERROR(); 3868585484eSchristos #endif 3878585484eSchristos ev_uint8_t msg; 3888585484eSchristos 3898585484eSchristos if (evsig_base == NULL) { 3908585484eSchristos event_warnx( 3918585484eSchristos "%s: received signal %d, but have no base configured", 3928585484eSchristos __func__, sig); 3938585484eSchristos return; 3948585484eSchristos } 3958585484eSchristos 3968585484eSchristos #ifndef EVENT__HAVE_SIGACTION 3978585484eSchristos signal(sig, evsig_handler); 3988585484eSchristos #endif 3998585484eSchristos 4008585484eSchristos /* Wake up our notification mechanism */ 4018585484eSchristos msg = sig; 4028585484eSchristos #ifdef _WIN32 4038585484eSchristos send(evsig_base_fd, (char*)&msg, 1, 0); 4048585484eSchristos #else 4058585484eSchristos { 4068585484eSchristos int r = write(evsig_base_fd, (char*)&msg, 1); 4078585484eSchristos (void)r; /* Suppress 'unused return value' and 'unused var' */ 4088585484eSchristos } 4098585484eSchristos #endif 4108585484eSchristos errno = save_errno; 4118585484eSchristos #ifdef _WIN32 4128585484eSchristos EVUTIL_SET_SOCKET_ERROR(socket_errno); 4138585484eSchristos #endif 4148585484eSchristos } 4158585484eSchristos 4168585484eSchristos void 4178585484eSchristos evsig_dealloc_(struct event_base *base) 4188585484eSchristos { 4198585484eSchristos int i = 0; 4208585484eSchristos if (base->sig.ev_signal_added) { 4218585484eSchristos event_del(&base->sig.ev_signal); 4228585484eSchristos base->sig.ev_signal_added = 0; 4238585484eSchristos } 4248585484eSchristos /* debug event is created in evsig_init_/event_assign even when 4258585484eSchristos * ev_signal_added == 0, so unassign is required */ 4268585484eSchristos event_debug_unassign(&base->sig.ev_signal); 4278585484eSchristos 4288585484eSchristos for (i = 0; i < NSIG; ++i) { 4298585484eSchristos if (i < base->sig.sh_old_max && base->sig.sh_old[i] != NULL) 4308585484eSchristos evsig_restore_handler_(base, i); 4318585484eSchristos } 4328585484eSchristos EVSIGBASE_LOCK(); 4338585484eSchristos if (base == evsig_base) { 4348585484eSchristos evsig_base = NULL; 4358585484eSchristos evsig_base_n_signals_added = 0; 4368585484eSchristos evsig_base_fd = -1; 4378585484eSchristos } 4388585484eSchristos EVSIGBASE_UNLOCK(); 4398585484eSchristos 4408585484eSchristos if (base->sig.ev_signal_pair[0] != -1) { 4418585484eSchristos evutil_closesocket(base->sig.ev_signal_pair[0]); 4428585484eSchristos base->sig.ev_signal_pair[0] = -1; 4438585484eSchristos } 4448585484eSchristos if (base->sig.ev_signal_pair[1] != -1) { 4458585484eSchristos evutil_closesocket(base->sig.ev_signal_pair[1]); 4468585484eSchristos base->sig.ev_signal_pair[1] = -1; 4478585484eSchristos } 4488585484eSchristos base->sig.sh_old_max = 0; 4498585484eSchristos 4508585484eSchristos /* per index frees are handled in evsig_del() */ 4518585484eSchristos if (base->sig.sh_old) { 4528585484eSchristos mm_free(base->sig.sh_old); 4538585484eSchristos base->sig.sh_old = NULL; 4548585484eSchristos } 4558585484eSchristos } 4568585484eSchristos 4578585484eSchristos static void 4588585484eSchristos evsig_free_globals_locks(void) 4598585484eSchristos { 4608585484eSchristos #ifndef EVENT__DISABLE_THREAD_SUPPORT 4618585484eSchristos if (evsig_base_lock != NULL) { 4628585484eSchristos EVTHREAD_FREE_LOCK(evsig_base_lock, 0); 4638585484eSchristos evsig_base_lock = NULL; 4648585484eSchristos } 4658585484eSchristos #endif 4668585484eSchristos return; 4678585484eSchristos } 4688585484eSchristos 4698585484eSchristos void 4708585484eSchristos evsig_free_globals_(void) 4718585484eSchristos { 4728585484eSchristos evsig_free_globals_locks(); 4738585484eSchristos } 4748585484eSchristos 4758585484eSchristos #ifndef EVENT__DISABLE_THREAD_SUPPORT 4768585484eSchristos int 4778585484eSchristos evsig_global_setup_locks_(const int enable_locks) 4788585484eSchristos { 4798585484eSchristos EVTHREAD_SETUP_GLOBAL_LOCK(evsig_base_lock, 0); 4808585484eSchristos return 0; 4818585484eSchristos } 4828585484eSchristos 4838585484eSchristos #endif 484