1290001Sglebius/*	$OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $	*/
2290001Sglebius
3290001Sglebius/*
4290001Sglebius * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu>
5290001Sglebius * Copyright 2007-2012 Niels Provos and Nick Mathewson
6290001Sglebius *
7290001Sglebius * Redistribution and use in source and binary forms, with or without
8290001Sglebius * modification, are permitted provided that the following conditions
9290001Sglebius * are met:
10290001Sglebius * 1. Redistributions of source code must retain the above copyright
11290001Sglebius *    notice, this list of conditions and the following disclaimer.
12290001Sglebius * 2. Redistributions in binary form must reproduce the above copyright
13290001Sglebius *    notice, this list of conditions and the following disclaimer in the
14290001Sglebius *    documentation and/or other materials provided with the distribution.
15290001Sglebius * 3. The name of the author may not be used to endorse or promote products
16290001Sglebius *    derived from this software without specific prior written permission.
17290001Sglebius *
18290001Sglebius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19290001Sglebius * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20290001Sglebius * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21290001Sglebius * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22290001Sglebius * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23290001Sglebius * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24290001Sglebius * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25290001Sglebius * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26290001Sglebius * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27290001Sglebius * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28290001Sglebius */
29290001Sglebius#include "event2/event-config.h"
30290001Sglebius#include "evconfig-private.h"
31290001Sglebius
32290001Sglebius#ifdef _WIN32
33290001Sglebius#define WIN32_LEAN_AND_MEAN
34290001Sglebius#include <winsock2.h>
35290001Sglebius#include <windows.h>
36290001Sglebius#undef WIN32_LEAN_AND_MEAN
37290001Sglebius#endif
38290001Sglebius#include <sys/types.h>
39290001Sglebius#ifdef EVENT__HAVE_SYS_TIME_H
40290001Sglebius#include <sys/time.h>
41290001Sglebius#endif
42290001Sglebius#include <sys/queue.h>
43290001Sglebius#ifdef EVENT__HAVE_SYS_SOCKET_H
44290001Sglebius#include <sys/socket.h>
45290001Sglebius#endif
46290001Sglebius#include <signal.h>
47290001Sglebius#include <stdio.h>
48290001Sglebius#include <stdlib.h>
49290001Sglebius#include <string.h>
50290001Sglebius#ifdef EVENT__HAVE_UNISTD_H
51290001Sglebius#include <unistd.h>
52290001Sglebius#endif
53290001Sglebius#include <errno.h>
54290001Sglebius#ifdef EVENT__HAVE_FCNTL_H
55290001Sglebius#include <fcntl.h>
56290001Sglebius#endif
57290001Sglebius
58290001Sglebius#include "event2/event.h"
59290001Sglebius#include "event2/event_struct.h"
60290001Sglebius#include "event-internal.h"
61290001Sglebius#include "event2/util.h"
62290001Sglebius#include "evsignal-internal.h"
63290001Sglebius#include "log-internal.h"
64290001Sglebius#include "evmap-internal.h"
65290001Sglebius#include "evthread-internal.h"
66290001Sglebius
67290001Sglebius/*
68290001Sglebius  signal.c
69290001Sglebius
70290001Sglebius  This is the signal-handling implementation we use for backends that don't
71290001Sglebius  have a better way to do signal handling.  It uses sigaction() or signal()
72290001Sglebius  to set a signal handler, and a socket pair to tell the event base when
73290001Sglebius
74290001Sglebius  Note that I said "the event base" : only one event base can be set up to use
75290001Sglebius  this at a time.  For historical reasons and backward compatibility, if you
76290001Sglebius  add an event for a signal to event_base A, then add an event for a signal
77290001Sglebius  (any signal!) to event_base B, event_base B will get informed about the
78290001Sglebius  signal, but event_base A won't.
79290001Sglebius
80290001Sglebius  It would be neat to change this behavior in some future version of Libevent.
81290001Sglebius  kqueue already does something far more sensible.  We can make all backends
82290001Sglebius  on Linux do a reasonable thing using signalfd.
83290001Sglebius*/
84290001Sglebius
85290001Sglebius#ifndef _WIN32
86290001Sglebius/* Windows wants us to call our signal handlers as __cdecl.  Nobody else
87290001Sglebius * expects you to do anything crazy like this. */
88290001Sglebius#define __cdecl
89290001Sglebius#endif
90290001Sglebius
91290001Sglebiusstatic int evsig_add(struct event_base *, evutil_socket_t, short, short, void *);
92290001Sglebiusstatic int evsig_del(struct event_base *, evutil_socket_t, short, short, void *);
93290001Sglebius
94290001Sglebiusstatic const struct eventop evsigops = {
95290001Sglebius	"signal",
96290001Sglebius	NULL,
97290001Sglebius	evsig_add,
98290001Sglebius	evsig_del,
99290001Sglebius	NULL,
100290001Sglebius	NULL,
101290001Sglebius	0, 0, 0
102290001Sglebius};
103290001Sglebius
104290001Sglebius#ifndef EVENT__DISABLE_THREAD_SUPPORT
105290001Sglebius/* Lock for evsig_base and evsig_base_n_signals_added fields. */
106290001Sglebiusstatic void *evsig_base_lock = NULL;
107290001Sglebius#endif
108290001Sglebius/* The event base that's currently getting informed about signals. */
109290001Sglebiusstatic struct event_base *evsig_base = NULL;
110290001Sglebius/* A copy of evsig_base->sigev_n_signals_added. */
111290001Sglebiusstatic int evsig_base_n_signals_added = 0;
112290001Sglebiusstatic evutil_socket_t evsig_base_fd = -1;
113290001Sglebius
114290001Sglebiusstatic void __cdecl evsig_handler(int sig);
115290001Sglebius
116290001Sglebius#define EVSIGBASE_LOCK() EVLOCK_LOCK(evsig_base_lock, 0)
117290001Sglebius#define EVSIGBASE_UNLOCK() EVLOCK_UNLOCK(evsig_base_lock, 0)
118290001Sglebius
119290001Sglebiusvoid
120290001Sglebiusevsig_set_base_(struct event_base *base)
121290001Sglebius{
122290001Sglebius	EVSIGBASE_LOCK();
123290001Sglebius	evsig_base = base;
124290001Sglebius	evsig_base_n_signals_added = base->sig.ev_n_signals_added;
125290001Sglebius	evsig_base_fd = base->sig.ev_signal_pair[1];
126290001Sglebius	EVSIGBASE_UNLOCK();
127290001Sglebius}
128290001Sglebius
129290001Sglebius/* Callback for when the signal handler write a byte to our signaling socket */
130290001Sglebiusstatic void
131290001Sglebiusevsig_cb(evutil_socket_t fd, short what, void *arg)
132290001Sglebius{
133290001Sglebius	static char signals[1024];
134290001Sglebius	ev_ssize_t n;
135290001Sglebius	int i;
136290001Sglebius	int ncaught[NSIG];
137290001Sglebius	struct event_base *base;
138290001Sglebius
139290001Sglebius	base = arg;
140290001Sglebius
141290001Sglebius	memset(&ncaught, 0, sizeof(ncaught));
142290001Sglebius
143290001Sglebius	while (1) {
144290001Sglebius#ifdef _WIN32
145290001Sglebius		n = recv(fd, signals, sizeof(signals), 0);
146290001Sglebius#else
147290001Sglebius		n = read(fd, signals, sizeof(signals));
148290001Sglebius#endif
149290001Sglebius		if (n == -1) {
150290001Sglebius			int err = evutil_socket_geterror(fd);
151290001Sglebius			if (! EVUTIL_ERR_RW_RETRIABLE(err))
152290001Sglebius				event_sock_err(1, fd, "%s: recv", __func__);
153290001Sglebius			break;
154290001Sglebius		} else if (n == 0) {
155290001Sglebius			/* XXX warn? */
156290001Sglebius			break;
157290001Sglebius		}
158290001Sglebius		for (i = 0; i < n; ++i) {
159290001Sglebius			ev_uint8_t sig = signals[i];
160290001Sglebius			if (sig < NSIG)
161290001Sglebius				ncaught[sig]++;
162290001Sglebius		}
163290001Sglebius	}
164290001Sglebius
165290001Sglebius	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
166290001Sglebius	for (i = 0; i < NSIG; ++i) {
167290001Sglebius		if (ncaught[i])
168290001Sglebius			evmap_signal_active_(base, i, ncaught[i]);
169290001Sglebius	}
170290001Sglebius	EVBASE_RELEASE_LOCK(base, th_base_lock);
171290001Sglebius}
172290001Sglebius
173290001Sglebiusint
174290001Sglebiusevsig_init_(struct event_base *base)
175290001Sglebius{
176290001Sglebius	/*
177290001Sglebius	 * Our signal handler is going to write to one end of the socket
178290001Sglebius	 * pair to wake up our event loop.  The event loop then scans for
179290001Sglebius	 * signals that got delivered.
180290001Sglebius	 */
181290001Sglebius	if (evutil_make_internal_pipe_(base->sig.ev_signal_pair) == -1) {
182290001Sglebius#ifdef _WIN32
183290001Sglebius		/* Make this nonfatal on win32, where sometimes people
184290001Sglebius		   have localhost firewalled. */
185290001Sglebius		event_sock_warn(-1, "%s: socketpair", __func__);
186290001Sglebius#else
187290001Sglebius		event_sock_err(1, -1, "%s: socketpair", __func__);
188290001Sglebius#endif
189290001Sglebius		return -1;
190290001Sglebius	}
191290001Sglebius
192290001Sglebius	if (base->sig.sh_old) {
193290001Sglebius		mm_free(base->sig.sh_old);
194290001Sglebius	}
195290001Sglebius	base->sig.sh_old = NULL;
196290001Sglebius	base->sig.sh_old_max = 0;
197290001Sglebius
198290001Sglebius	event_assign(&base->sig.ev_signal, base, base->sig.ev_signal_pair[0],
199290001Sglebius		EV_READ | EV_PERSIST, evsig_cb, base);
200290001Sglebius
201290001Sglebius	base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL;
202290001Sglebius	event_priority_set(&base->sig.ev_signal, 0);
203290001Sglebius
204290001Sglebius	base->evsigsel = &evsigops;
205290001Sglebius
206290001Sglebius	return 0;
207290001Sglebius}
208290001Sglebius
209290001Sglebius/* Helper: set the signal handler for evsignal to handler in base, so that
210290001Sglebius * we can restore the original handler when we clear the current one. */
211290001Sglebiusint
212290001Sglebiusevsig_set_handler_(struct event_base *base,
213290001Sglebius    int evsignal, void (__cdecl *handler)(int))
214290001Sglebius{
215290001Sglebius#ifdef EVENT__HAVE_SIGACTION
216290001Sglebius	struct sigaction sa;
217290001Sglebius#else
218290001Sglebius	ev_sighandler_t sh;
219290001Sglebius#endif
220290001Sglebius	struct evsig_info *sig = &base->sig;
221290001Sglebius	void *p;
222290001Sglebius
223290001Sglebius	/*
224290001Sglebius	 * resize saved signal handler array up to the highest signal number.
225290001Sglebius	 * a dynamic array is used to keep footprint on the low side.
226290001Sglebius	 */
227290001Sglebius	if (evsignal >= sig->sh_old_max) {
228290001Sglebius		int new_max = evsignal + 1;
229290001Sglebius		event_debug(("%s: evsignal (%d) >= sh_old_max (%d), resizing",
230290001Sglebius			    __func__, evsignal, sig->sh_old_max));
231290001Sglebius		p = mm_realloc(sig->sh_old, new_max * sizeof(*sig->sh_old));
232290001Sglebius		if (p == NULL) {
233290001Sglebius			event_warn("realloc");
234290001Sglebius			return (-1);
235290001Sglebius		}
236290001Sglebius
237290001Sglebius		memset((char *)p + sig->sh_old_max * sizeof(*sig->sh_old),
238290001Sglebius		    0, (new_max - sig->sh_old_max) * sizeof(*sig->sh_old));
239290001Sglebius
240290001Sglebius		sig->sh_old_max = new_max;
241290001Sglebius		sig->sh_old = p;
242290001Sglebius	}
243290001Sglebius
244290001Sglebius	/* allocate space for previous handler out of dynamic array */
245290001Sglebius	sig->sh_old[evsignal] = mm_malloc(sizeof *sig->sh_old[evsignal]);
246290001Sglebius	if (sig->sh_old[evsignal] == NULL) {
247290001Sglebius		event_warn("malloc");
248290001Sglebius		return (-1);
249290001Sglebius	}
250290001Sglebius
251290001Sglebius	/* save previous handler and setup new handler */
252290001Sglebius#ifdef EVENT__HAVE_SIGACTION
253290001Sglebius	memset(&sa, 0, sizeof(sa));
254290001Sglebius	sa.sa_handler = handler;
255290001Sglebius	sa.sa_flags |= SA_RESTART;
256290001Sglebius	sigfillset(&sa.sa_mask);
257290001Sglebius
258290001Sglebius	if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) {
259290001Sglebius		event_warn("sigaction");
260290001Sglebius		mm_free(sig->sh_old[evsignal]);
261290001Sglebius		sig->sh_old[evsignal] = NULL;
262290001Sglebius		return (-1);
263290001Sglebius	}
264290001Sglebius#else
265290001Sglebius	if ((sh = signal(evsignal, handler)) == SIG_ERR) {
266290001Sglebius		event_warn("signal");
267290001Sglebius		mm_free(sig->sh_old[evsignal]);
268290001Sglebius		sig->sh_old[evsignal] = NULL;
269290001Sglebius		return (-1);
270290001Sglebius	}
271290001Sglebius	*sig->sh_old[evsignal] = sh;
272290001Sglebius#endif
273290001Sglebius
274290001Sglebius	return (0);
275290001Sglebius}
276290001Sglebius
277290001Sglebiusstatic int
278290001Sglebiusevsig_add(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p)
279290001Sglebius{
280290001Sglebius	struct evsig_info *sig = &base->sig;
281290001Sglebius	(void)p;
282290001Sglebius
283290001Sglebius	EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG);
284290001Sglebius
285290001Sglebius	/* catch signals if they happen quickly */
286290001Sglebius	EVSIGBASE_LOCK();
287290001Sglebius	if (evsig_base != base && evsig_base_n_signals_added) {
288290001Sglebius		event_warnx("Added a signal to event base %p with signals "
289290001Sglebius		    "already added to event_base %p.  Only one can have "
290290001Sglebius		    "signals at a time with the %s backend.  The base with "
291290001Sglebius		    "the most recently added signal or the most recent "
292290001Sglebius		    "event_base_loop() call gets preference; do "
293290001Sglebius		    "not rely on this behavior in future Libevent versions.",
294290001Sglebius		    base, evsig_base, base->evsel->name);
295290001Sglebius	}
296290001Sglebius	evsig_base = base;
297290001Sglebius	evsig_base_n_signals_added = ++sig->ev_n_signals_added;
298290001Sglebius	evsig_base_fd = base->sig.ev_signal_pair[1];
299290001Sglebius	EVSIGBASE_UNLOCK();
300290001Sglebius
301290001Sglebius	event_debug(("%s: %d: changing signal handler", __func__, (int)evsignal));
302290001Sglebius	if (evsig_set_handler_(base, (int)evsignal, evsig_handler) == -1) {
303290001Sglebius		goto err;
304290001Sglebius	}
305290001Sglebius
306290001Sglebius
307290001Sglebius	if (!sig->ev_signal_added) {
308290001Sglebius		if (event_add_nolock_(&sig->ev_signal, NULL, 0))
309290001Sglebius			goto err;
310290001Sglebius		sig->ev_signal_added = 1;
311290001Sglebius	}
312290001Sglebius
313290001Sglebius	return (0);
314290001Sglebius
315290001Sglebiuserr:
316290001Sglebius	EVSIGBASE_LOCK();
317290001Sglebius	--evsig_base_n_signals_added;
318290001Sglebius	--sig->ev_n_signals_added;
319290001Sglebius	EVSIGBASE_UNLOCK();
320290001Sglebius	return (-1);
321290001Sglebius}
322290001Sglebius
323290001Sglebiusint
324290001Sglebiusevsig_restore_handler_(struct event_base *base, int evsignal)
325290001Sglebius{
326290001Sglebius	int ret = 0;
327290001Sglebius	struct evsig_info *sig = &base->sig;
328290001Sglebius#ifdef EVENT__HAVE_SIGACTION
329290001Sglebius	struct sigaction *sh;
330290001Sglebius#else
331290001Sglebius	ev_sighandler_t *sh;
332290001Sglebius#endif
333290001Sglebius
334290001Sglebius	if (evsignal >= sig->sh_old_max) {
335290001Sglebius		/* Can't actually restore. */
336290001Sglebius		/* XXXX.*/
337290001Sglebius		return 0;
338290001Sglebius	}
339290001Sglebius
340290001Sglebius	/* restore previous handler */
341290001Sglebius	sh = sig->sh_old[evsignal];
342290001Sglebius	sig->sh_old[evsignal] = NULL;
343290001Sglebius#ifdef EVENT__HAVE_SIGACTION
344290001Sglebius	if (sigaction(evsignal, sh, NULL) == -1) {
345290001Sglebius		event_warn("sigaction");
346290001Sglebius		ret = -1;
347290001Sglebius	}
348290001Sglebius#else
349290001Sglebius	if (signal(evsignal, *sh) == SIG_ERR) {
350290001Sglebius		event_warn("signal");
351290001Sglebius		ret = -1;
352290001Sglebius	}
353290001Sglebius#endif
354290001Sglebius
355290001Sglebius	mm_free(sh);
356290001Sglebius
357290001Sglebius	return ret;
358290001Sglebius}
359290001Sglebius
360290001Sglebiusstatic int
361290001Sglebiusevsig_del(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p)
362290001Sglebius{
363290001Sglebius	EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG);
364290001Sglebius
365290001Sglebius	event_debug(("%s: "EV_SOCK_FMT": restoring signal handler",
366290001Sglebius		__func__, EV_SOCK_ARG(evsignal)));
367290001Sglebius
368290001Sglebius	EVSIGBASE_LOCK();
369290001Sglebius	--evsig_base_n_signals_added;
370290001Sglebius	--base->sig.ev_n_signals_added;
371290001Sglebius	EVSIGBASE_UNLOCK();
372290001Sglebius
373290001Sglebius	return (evsig_restore_handler_(base, (int)evsignal));
374290001Sglebius}
375290001Sglebius
376290001Sglebiusstatic void __cdecl
377290001Sglebiusevsig_handler(int sig)
378290001Sglebius{
379290001Sglebius	int save_errno = errno;
380290001Sglebius#ifdef _WIN32
381290001Sglebius	int socket_errno = EVUTIL_SOCKET_ERROR();
382290001Sglebius#endif
383290001Sglebius	ev_uint8_t msg;
384290001Sglebius
385290001Sglebius	if (evsig_base == NULL) {
386290001Sglebius		event_warnx(
387290001Sglebius			"%s: received signal %d, but have no base configured",
388290001Sglebius			__func__, sig);
389290001Sglebius		return;
390290001Sglebius	}
391290001Sglebius
392290001Sglebius#ifndef EVENT__HAVE_SIGACTION
393290001Sglebius	signal(sig, evsig_handler);
394290001Sglebius#endif
395290001Sglebius
396290001Sglebius	/* Wake up our notification mechanism */
397290001Sglebius	msg = sig;
398290001Sglebius#ifdef _WIN32
399290001Sglebius	send(evsig_base_fd, (char*)&msg, 1, 0);
400290001Sglebius#else
401290001Sglebius	{
402290001Sglebius		int r = write(evsig_base_fd, (char*)&msg, 1);
403290001Sglebius		(void)r; /* Suppress 'unused return value' and 'unused var' */
404290001Sglebius	}
405290001Sglebius#endif
406290001Sglebius	errno = save_errno;
407290001Sglebius#ifdef _WIN32
408290001Sglebius	EVUTIL_SET_SOCKET_ERROR(socket_errno);
409290001Sglebius#endif
410290001Sglebius}
411290001Sglebius
412290001Sglebiusvoid
413290001Sglebiusevsig_dealloc_(struct event_base *base)
414290001Sglebius{
415290001Sglebius	int i = 0;
416290001Sglebius	if (base->sig.ev_signal_added) {
417290001Sglebius		event_del(&base->sig.ev_signal);
418290001Sglebius		base->sig.ev_signal_added = 0;
419290001Sglebius	}
420290001Sglebius	/* debug event is created in evsig_init_/event_assign even when
421290001Sglebius	 * ev_signal_added == 0, so unassign is required */
422290001Sglebius	event_debug_unassign(&base->sig.ev_signal);
423290001Sglebius
424290001Sglebius	for (i = 0; i < NSIG; ++i) {
425290001Sglebius		if (i < base->sig.sh_old_max && base->sig.sh_old[i] != NULL)
426290001Sglebius			evsig_restore_handler_(base, i);
427290001Sglebius	}
428290001Sglebius	EVSIGBASE_LOCK();
429290001Sglebius	if (base == evsig_base) {
430290001Sglebius		evsig_base = NULL;
431290001Sglebius		evsig_base_n_signals_added = 0;
432290001Sglebius		evsig_base_fd = -1;
433290001Sglebius	}
434290001Sglebius	EVSIGBASE_UNLOCK();
435290001Sglebius
436290001Sglebius	if (base->sig.ev_signal_pair[0] != -1) {
437290001Sglebius		evutil_closesocket(base->sig.ev_signal_pair[0]);
438290001Sglebius		base->sig.ev_signal_pair[0] = -1;
439290001Sglebius	}
440290001Sglebius	if (base->sig.ev_signal_pair[1] != -1) {
441290001Sglebius		evutil_closesocket(base->sig.ev_signal_pair[1]);
442290001Sglebius		base->sig.ev_signal_pair[1] = -1;
443290001Sglebius	}
444290001Sglebius	base->sig.sh_old_max = 0;
445290001Sglebius
446290001Sglebius	/* per index frees are handled in evsig_del() */
447290001Sglebius	if (base->sig.sh_old) {
448290001Sglebius		mm_free(base->sig.sh_old);
449290001Sglebius		base->sig.sh_old = NULL;
450290001Sglebius	}
451290001Sglebius}
452290001Sglebius
453290001Sglebiusstatic void
454290001Sglebiusevsig_free_globals_locks(void)
455290001Sglebius{
456290001Sglebius#ifndef EVENT__DISABLE_THREAD_SUPPORT
457290001Sglebius	if (evsig_base_lock != NULL) {
458290001Sglebius		EVTHREAD_FREE_LOCK(evsig_base_lock, 0);
459290001Sglebius		evsig_base_lock = NULL;
460290001Sglebius	}
461290001Sglebius#endif
462290001Sglebius	return;
463290001Sglebius}
464290001Sglebius
465290001Sglebiusvoid
466290001Sglebiusevsig_free_globals_(void)
467290001Sglebius{
468290001Sglebius	evsig_free_globals_locks();
469290001Sglebius}
470290001Sglebius
471290001Sglebius#ifndef EVENT__DISABLE_THREAD_SUPPORT
472290001Sglebiusint
473290001Sglebiusevsig_global_setup_locks_(const int enable_locks)
474290001Sglebius{
475290001Sglebius	EVTHREAD_SETUP_GLOBAL_LOCK(evsig_base_lock, 0);
476290001Sglebius	return 0;
477290001Sglebius}
478290001Sglebius
479290001Sglebius#endif
480