1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/third_party/libevent/signal.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,445 @@ 1.4 +/* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ 1.5 + 1.6 +/* 1.7 + * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu> 1.8 + * Copyright 2007-2012 Niels Provos and Nick Mathewson 1.9 + * 1.10 + * Redistribution and use in source and binary forms, with or without 1.11 + * modification, are permitted provided that the following conditions 1.12 + * are met: 1.13 + * 1. Redistributions of source code must retain the above copyright 1.14 + * notice, this list of conditions and the following disclaimer. 1.15 + * 2. Redistributions in binary form must reproduce the above copyright 1.16 + * notice, this list of conditions and the following disclaimer in the 1.17 + * documentation and/or other materials provided with the distribution. 1.18 + * 3. The name of the author may not be used to endorse or promote products 1.19 + * derived from this software without specific prior written permission. 1.20 + * 1.21 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1.22 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1.23 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1.24 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1.25 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1.26 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.27 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.28 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.29 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 1.30 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.31 + */ 1.32 +#include "event2/event-config.h" 1.33 + 1.34 +#ifdef WIN32 1.35 +#define WIN32_LEAN_AND_MEAN 1.36 +#include <winsock2.h> 1.37 +#include <windows.h> 1.38 +#undef WIN32_LEAN_AND_MEAN 1.39 +#endif 1.40 +#include <sys/types.h> 1.41 +#ifdef _EVENT_HAVE_SYS_TIME_H 1.42 +#include <sys/time.h> 1.43 +#endif 1.44 +#include <sys/queue.h> 1.45 +#ifdef _EVENT_HAVE_SYS_SOCKET_H 1.46 +#include <sys/socket.h> 1.47 +#endif 1.48 +#include <signal.h> 1.49 +#include <stdio.h> 1.50 +#include <stdlib.h> 1.51 +#include <string.h> 1.52 +#ifdef _EVENT_HAVE_UNISTD_H 1.53 +#include <unistd.h> 1.54 +#endif 1.55 +#include <errno.h> 1.56 +#ifdef _EVENT_HAVE_FCNTL_H 1.57 +#include <fcntl.h> 1.58 +#endif 1.59 + 1.60 +#include "event2/event.h" 1.61 +#include "event2/event_struct.h" 1.62 +#include "event-internal.h" 1.63 +#include "event2/util.h" 1.64 +#include "evsignal-internal.h" 1.65 +#include "log-internal.h" 1.66 +#include "evmap-internal.h" 1.67 +#include "evthread-internal.h" 1.68 + 1.69 +/* 1.70 + signal.c 1.71 + 1.72 + This is the signal-handling implementation we use for backends that don't 1.73 + have a better way to do signal handling. It uses sigaction() or signal() 1.74 + to set a signal handler, and a socket pair to tell the event base when 1.75 + 1.76 + Note that I said "the event base" : only one event base can be set up to use 1.77 + this at a time. For historical reasons and backward compatibility, if you 1.78 + add an event for a signal to event_base A, then add an event for a signal 1.79 + (any signal!) to event_base B, event_base B will get informed about the 1.80 + signal, but event_base A won't. 1.81 + 1.82 + It would be neat to change this behavior in some future version of Libevent. 1.83 + kqueue already does something far more sensible. We can make all backends 1.84 + on Linux do a reasonable thing using signalfd. 1.85 +*/ 1.86 + 1.87 +#ifndef WIN32 1.88 +/* Windows wants us to call our signal handlers as __cdecl. Nobody else 1.89 + * expects you to do anything crazy like this. */ 1.90 +#define __cdecl 1.91 +#endif 1.92 + 1.93 +static int evsig_add(struct event_base *, evutil_socket_t, short, short, void *); 1.94 +static int evsig_del(struct event_base *, evutil_socket_t, short, short, void *); 1.95 + 1.96 +static const struct eventop evsigops = { 1.97 + "signal", 1.98 + NULL, 1.99 + evsig_add, 1.100 + evsig_del, 1.101 + NULL, 1.102 + NULL, 1.103 + 0, 0, 0 1.104 +}; 1.105 + 1.106 +#ifndef _EVENT_DISABLE_THREAD_SUPPORT 1.107 +/* Lock for evsig_base and evsig_base_n_signals_added fields. */ 1.108 +static void *evsig_base_lock = NULL; 1.109 +#endif 1.110 +/* The event base that's currently getting informed about signals. */ 1.111 +static struct event_base *evsig_base = NULL; 1.112 +/* A copy of evsig_base->sigev_n_signals_added. */ 1.113 +static int evsig_base_n_signals_added = 0; 1.114 +static evutil_socket_t evsig_base_fd = -1; 1.115 + 1.116 +static void __cdecl evsig_handler(int sig); 1.117 + 1.118 +#define EVSIGBASE_LOCK() EVLOCK_LOCK(evsig_base_lock, 0) 1.119 +#define EVSIGBASE_UNLOCK() EVLOCK_UNLOCK(evsig_base_lock, 0) 1.120 + 1.121 +void 1.122 +evsig_set_base(struct event_base *base) 1.123 +{ 1.124 + EVSIGBASE_LOCK(); 1.125 + evsig_base = base; 1.126 + evsig_base_n_signals_added = base->sig.ev_n_signals_added; 1.127 + evsig_base_fd = base->sig.ev_signal_pair[0]; 1.128 + EVSIGBASE_UNLOCK(); 1.129 +} 1.130 + 1.131 +/* Callback for when the signal handler write a byte to our signaling socket */ 1.132 +static void 1.133 +evsig_cb(evutil_socket_t fd, short what, void *arg) 1.134 +{ 1.135 + static char signals[1024]; 1.136 + ev_ssize_t n; 1.137 + int i; 1.138 + int ncaught[NSIG]; 1.139 + struct event_base *base; 1.140 + 1.141 + base = arg; 1.142 + 1.143 + memset(&ncaught, 0, sizeof(ncaught)); 1.144 + 1.145 + while (1) { 1.146 + n = recv(fd, signals, sizeof(signals), 0); 1.147 + if (n == -1) { 1.148 + int err = evutil_socket_geterror(fd); 1.149 + if (! EVUTIL_ERR_RW_RETRIABLE(err)) 1.150 + event_sock_err(1, fd, "%s: recv", __func__); 1.151 + break; 1.152 + } else if (n == 0) { 1.153 + /* XXX warn? */ 1.154 + break; 1.155 + } 1.156 + for (i = 0; i < n; ++i) { 1.157 + ev_uint8_t sig = signals[i]; 1.158 + if (sig < NSIG) 1.159 + ncaught[sig]++; 1.160 + } 1.161 + } 1.162 + 1.163 + EVBASE_ACQUIRE_LOCK(base, th_base_lock); 1.164 + for (i = 0; i < NSIG; ++i) { 1.165 + if (ncaught[i]) 1.166 + evmap_signal_active(base, i, ncaught[i]); 1.167 + } 1.168 + EVBASE_RELEASE_LOCK(base, th_base_lock); 1.169 +} 1.170 + 1.171 +int 1.172 +evsig_init(struct event_base *base) 1.173 +{ 1.174 + /* 1.175 + * Our signal handler is going to write to one end of the socket 1.176 + * pair to wake up our event loop. The event loop then scans for 1.177 + * signals that got delivered. 1.178 + */ 1.179 + if (evutil_socketpair( 1.180 + AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1) { 1.181 +#ifdef WIN32 1.182 + /* Make this nonfatal on win32, where sometimes people 1.183 + have localhost firewalled. */ 1.184 + event_sock_warn(-1, "%s: socketpair", __func__); 1.185 +#else 1.186 + event_sock_err(1, -1, "%s: socketpair", __func__); 1.187 +#endif 1.188 + return -1; 1.189 + } 1.190 + 1.191 + evutil_make_socket_closeonexec(base->sig.ev_signal_pair[0]); 1.192 + evutil_make_socket_closeonexec(base->sig.ev_signal_pair[1]); 1.193 + base->sig.sh_old = NULL; 1.194 + base->sig.sh_old_max = 0; 1.195 + 1.196 + evutil_make_socket_nonblocking(base->sig.ev_signal_pair[0]); 1.197 + evutil_make_socket_nonblocking(base->sig.ev_signal_pair[1]); 1.198 + 1.199 + event_assign(&base->sig.ev_signal, base, base->sig.ev_signal_pair[1], 1.200 + EV_READ | EV_PERSIST, evsig_cb, base); 1.201 + 1.202 + base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL; 1.203 + event_priority_set(&base->sig.ev_signal, 0); 1.204 + 1.205 + base->evsigsel = &evsigops; 1.206 + 1.207 + return 0; 1.208 +} 1.209 + 1.210 +/* Helper: set the signal handler for evsignal to handler in base, so that 1.211 + * we can restore the original handler when we clear the current one. */ 1.212 +int 1.213 +_evsig_set_handler(struct event_base *base, 1.214 + int evsignal, void (__cdecl *handler)(int)) 1.215 +{ 1.216 +#ifdef _EVENT_HAVE_SIGACTION 1.217 + struct sigaction sa; 1.218 +#else 1.219 + ev_sighandler_t sh; 1.220 +#endif 1.221 + struct evsig_info *sig = &base->sig; 1.222 + void *p; 1.223 + 1.224 + /* 1.225 + * resize saved signal handler array up to the highest signal number. 1.226 + * a dynamic array is used to keep footprint on the low side. 1.227 + */ 1.228 + if (evsignal >= sig->sh_old_max) { 1.229 + int new_max = evsignal + 1; 1.230 + event_debug(("%s: evsignal (%d) >= sh_old_max (%d), resizing", 1.231 + __func__, evsignal, sig->sh_old_max)); 1.232 + p = mm_realloc(sig->sh_old, new_max * sizeof(*sig->sh_old)); 1.233 + if (p == NULL) { 1.234 + event_warn("realloc"); 1.235 + return (-1); 1.236 + } 1.237 + 1.238 + memset((char *)p + sig->sh_old_max * sizeof(*sig->sh_old), 1.239 + 0, (new_max - sig->sh_old_max) * sizeof(*sig->sh_old)); 1.240 + 1.241 + sig->sh_old_max = new_max; 1.242 + sig->sh_old = p; 1.243 + } 1.244 + 1.245 + /* allocate space for previous handler out of dynamic array */ 1.246 + sig->sh_old[evsignal] = mm_malloc(sizeof *sig->sh_old[evsignal]); 1.247 + if (sig->sh_old[evsignal] == NULL) { 1.248 + event_warn("malloc"); 1.249 + return (-1); 1.250 + } 1.251 + 1.252 + /* save previous handler and setup new handler */ 1.253 +#ifdef _EVENT_HAVE_SIGACTION 1.254 + memset(&sa, 0, sizeof(sa)); 1.255 + sa.sa_handler = handler; 1.256 + sa.sa_flags |= SA_RESTART; 1.257 + sigfillset(&sa.sa_mask); 1.258 + 1.259 + if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) { 1.260 + event_warn("sigaction"); 1.261 + mm_free(sig->sh_old[evsignal]); 1.262 + sig->sh_old[evsignal] = NULL; 1.263 + return (-1); 1.264 + } 1.265 +#else 1.266 + if ((sh = signal(evsignal, handler)) == SIG_ERR) { 1.267 + event_warn("signal"); 1.268 + mm_free(sig->sh_old[evsignal]); 1.269 + sig->sh_old[evsignal] = NULL; 1.270 + return (-1); 1.271 + } 1.272 + *sig->sh_old[evsignal] = sh; 1.273 +#endif 1.274 + 1.275 + return (0); 1.276 +} 1.277 + 1.278 +static int 1.279 +evsig_add(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p) 1.280 +{ 1.281 + struct evsig_info *sig = &base->sig; 1.282 + (void)p; 1.283 + 1.284 + EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG); 1.285 + 1.286 + /* catch signals if they happen quickly */ 1.287 + EVSIGBASE_LOCK(); 1.288 + if (evsig_base != base && evsig_base_n_signals_added) { 1.289 + event_warnx("Added a signal to event base %p with signals " 1.290 + "already added to event_base %p. Only one can have " 1.291 + "signals at a time with the %s backend. The base with " 1.292 + "the most recently added signal or the most recent " 1.293 + "event_base_loop() call gets preference; do " 1.294 + "not rely on this behavior in future Libevent versions.", 1.295 + base, evsig_base, base->evsel->name); 1.296 + } 1.297 + evsig_base = base; 1.298 + evsig_base_n_signals_added = ++sig->ev_n_signals_added; 1.299 + evsig_base_fd = base->sig.ev_signal_pair[0]; 1.300 + EVSIGBASE_UNLOCK(); 1.301 + 1.302 + event_debug(("%s: %d: changing signal handler", __func__, (int)evsignal)); 1.303 + if (_evsig_set_handler(base, (int)evsignal, evsig_handler) == -1) { 1.304 + goto err; 1.305 + } 1.306 + 1.307 + 1.308 + if (!sig->ev_signal_added) { 1.309 + if (event_add(&sig->ev_signal, NULL)) 1.310 + goto err; 1.311 + sig->ev_signal_added = 1; 1.312 + } 1.313 + 1.314 + return (0); 1.315 + 1.316 +err: 1.317 + EVSIGBASE_LOCK(); 1.318 + --evsig_base_n_signals_added; 1.319 + --sig->ev_n_signals_added; 1.320 + EVSIGBASE_UNLOCK(); 1.321 + return (-1); 1.322 +} 1.323 + 1.324 +int 1.325 +_evsig_restore_handler(struct event_base *base, int evsignal) 1.326 +{ 1.327 + int ret = 0; 1.328 + struct evsig_info *sig = &base->sig; 1.329 +#ifdef _EVENT_HAVE_SIGACTION 1.330 + struct sigaction *sh; 1.331 +#else 1.332 + ev_sighandler_t *sh; 1.333 +#endif 1.334 + 1.335 + /* restore previous handler */ 1.336 + sh = sig->sh_old[evsignal]; 1.337 + sig->sh_old[evsignal] = NULL; 1.338 +#ifdef _EVENT_HAVE_SIGACTION 1.339 + if (sigaction(evsignal, sh, NULL) == -1) { 1.340 + event_warn("sigaction"); 1.341 + ret = -1; 1.342 + } 1.343 +#else 1.344 + if (signal(evsignal, *sh) == SIG_ERR) { 1.345 + event_warn("signal"); 1.346 + ret = -1; 1.347 + } 1.348 +#endif 1.349 + 1.350 + mm_free(sh); 1.351 + 1.352 + return ret; 1.353 +} 1.354 + 1.355 +static int 1.356 +evsig_del(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p) 1.357 +{ 1.358 + EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG); 1.359 + 1.360 + event_debug(("%s: "EV_SOCK_FMT": restoring signal handler", 1.361 + __func__, EV_SOCK_ARG(evsignal))); 1.362 + 1.363 + EVSIGBASE_LOCK(); 1.364 + --evsig_base_n_signals_added; 1.365 + --base->sig.ev_n_signals_added; 1.366 + EVSIGBASE_UNLOCK(); 1.367 + 1.368 + return (_evsig_restore_handler(base, (int)evsignal)); 1.369 +} 1.370 + 1.371 +static void __cdecl 1.372 +evsig_handler(int sig) 1.373 +{ 1.374 + int save_errno = errno; 1.375 +#ifdef WIN32 1.376 + int socket_errno = EVUTIL_SOCKET_ERROR(); 1.377 +#endif 1.378 + ev_uint8_t msg; 1.379 + 1.380 + if (evsig_base == NULL) { 1.381 + event_warnx( 1.382 + "%s: received signal %d, but have no base configured", 1.383 + __func__, sig); 1.384 + return; 1.385 + } 1.386 + 1.387 +#ifndef _EVENT_HAVE_SIGACTION 1.388 + signal(sig, evsig_handler); 1.389 +#endif 1.390 + 1.391 + /* Wake up our notification mechanism */ 1.392 + msg = sig; 1.393 + send(evsig_base_fd, (char*)&msg, 1, 0); 1.394 + errno = save_errno; 1.395 +#ifdef WIN32 1.396 + EVUTIL_SET_SOCKET_ERROR(socket_errno); 1.397 +#endif 1.398 +} 1.399 + 1.400 +void 1.401 +evsig_dealloc(struct event_base *base) 1.402 +{ 1.403 + int i = 0; 1.404 + if (base->sig.ev_signal_added) { 1.405 + event_del(&base->sig.ev_signal); 1.406 + base->sig.ev_signal_added = 0; 1.407 + } 1.408 + /* debug event is created in evsig_init/event_assign even when 1.409 + * ev_signal_added == 0, so unassign is required */ 1.410 + event_debug_unassign(&base->sig.ev_signal); 1.411 + 1.412 + for (i = 0; i < NSIG; ++i) { 1.413 + if (i < base->sig.sh_old_max && base->sig.sh_old[i] != NULL) 1.414 + _evsig_restore_handler(base, i); 1.415 + } 1.416 + EVSIGBASE_LOCK(); 1.417 + if (base == evsig_base) { 1.418 + evsig_base = NULL; 1.419 + evsig_base_n_signals_added = 0; 1.420 + evsig_base_fd = -1; 1.421 + } 1.422 + EVSIGBASE_UNLOCK(); 1.423 + 1.424 + if (base->sig.ev_signal_pair[0] != -1) { 1.425 + evutil_closesocket(base->sig.ev_signal_pair[0]); 1.426 + base->sig.ev_signal_pair[0] = -1; 1.427 + } 1.428 + if (base->sig.ev_signal_pair[1] != -1) { 1.429 + evutil_closesocket(base->sig.ev_signal_pair[1]); 1.430 + base->sig.ev_signal_pair[1] = -1; 1.431 + } 1.432 + base->sig.sh_old_max = 0; 1.433 + 1.434 + /* per index frees are handled in evsig_del() */ 1.435 + if (base->sig.sh_old) { 1.436 + mm_free(base->sig.sh_old); 1.437 + base->sig.sh_old = NULL; 1.438 + } 1.439 +} 1.440 + 1.441 +#ifndef _EVENT_DISABLE_THREAD_SUPPORT 1.442 +int 1.443 +evsig_global_setup_locks_(const int enable_locks) 1.444 +{ 1.445 + EVTHREAD_SETUP_GLOBAL_LOCK(evsig_base_lock, 0); 1.446 + return 0; 1.447 +} 1.448 +#endif