signal.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. /* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
  2. /*
  3. * Copyright 2000-2007 Niels Provos <provos@citi.umich.edu>
  4. * Copyright 2007-2012 Niels Provos and Nick Mathewson
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. The name of the author may not be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include "event2/event-config.h"
  29. #include "evconfig-private.h"
  30. #ifdef _WIN32
  31. #define WIN32_LEAN_AND_MEAN
  32. #include <winsock2.h>
  33. #include <windows.h>
  34. #undef WIN32_LEAN_AND_MEAN
  35. #endif
  36. #include <sys/types.h>
  37. #ifdef EVENT__HAVE_SYS_TIME_H
  38. #include <sys/time.h>
  39. #endif
  40. #include <sys/queue.h>
  41. #ifdef EVENT__HAVE_SYS_SOCKET_H
  42. #include <sys/socket.h>
  43. #endif
  44. #include <signal.h>
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <string.h>
  48. #ifdef EVENT__HAVE_UNISTD_H
  49. #include <unistd.h>
  50. #endif
  51. #include <errno.h>
  52. #ifdef EVENT__HAVE_FCNTL_H
  53. #include <fcntl.h>
  54. #endif
  55. #include "event2/event.h"
  56. #include "event2/event_struct.h"
  57. #include "event-internal.h"
  58. #include "event2/util.h"
  59. #include "evsignal-internal.h"
  60. #include "log-internal.h"
  61. #include "evmap-internal.h"
  62. #include "evthread-internal.h"
  63. /*
  64. signal.c
  65. This is the signal-handling implementation we use for backends that don't
  66. have a better way to do signal handling. It uses sigaction() or signal()
  67. to set a signal handler, and a socket pair to tell the event base when
  68. Note that I said "the event base" : only one event base can be set up to use
  69. this at a time. For historical reasons and backward compatibility, if you
  70. add an event for a signal to event_base A, then add an event for a signal
  71. (any signal!) to event_base B, event_base B will get informed about the
  72. signal, but event_base A won't.
  73. It would be neat to change this behavior in some future version of Libevent.
  74. kqueue already does something far more sensible. We can make all backends
  75. on Linux do a reasonable thing using signalfd.
  76. */
  77. #ifndef _WIN32
  78. /* Windows wants us to call our signal handlers as __cdecl. Nobody else
  79. * expects you to do anything crazy like this. */
  80. #ifndef __cdecl
  81. #define __cdecl
  82. #endif
  83. #endif
  84. static int evsig_add(struct event_base *, evutil_socket_t, short, short, void *);
  85. static int evsig_del(struct event_base *, evutil_socket_t, short, short, void *);
  86. static const struct eventop evsigops = {
  87. "signal",
  88. NULL,
  89. evsig_add,
  90. evsig_del,
  91. NULL,
  92. NULL,
  93. 0, 0, 0
  94. };
  95. #ifndef EVENT__DISABLE_THREAD_SUPPORT
  96. /* Lock for evsig_base and evsig_base_n_signals_added fields. */
  97. static void *evsig_base_lock = NULL;
  98. #endif
  99. /* The event base that's currently getting informed about signals. */
  100. static struct event_base *evsig_base = NULL;
  101. /* A copy of evsig_base->sigev_n_signals_added. */
  102. static int evsig_base_n_signals_added = 0;
  103. static evutil_socket_t evsig_base_fd = -1;
  104. static void __cdecl evsig_handler(int sig);
  105. #define EVSIGBASE_LOCK() EVLOCK_LOCK(evsig_base_lock, 0)
  106. #define EVSIGBASE_UNLOCK() EVLOCK_UNLOCK(evsig_base_lock, 0)
  107. void
  108. evsig_set_base_(struct event_base *base)
  109. {
  110. EVSIGBASE_LOCK();
  111. evsig_base = base;
  112. evsig_base_n_signals_added = base->sig.ev_n_signals_added;
  113. evsig_base_fd = base->sig.ev_signal_pair[1];
  114. EVSIGBASE_UNLOCK();
  115. }
  116. /* Callback for when the signal handler write a byte to our signaling socket */
  117. static void
  118. evsig_cb(evutil_socket_t fd, short what, void *arg)
  119. {
  120. static char signals[1024];
  121. ev_ssize_t n;
  122. int i;
  123. int ncaught[NSIG];
  124. struct event_base *base;
  125. base = arg;
  126. memset(&ncaught, 0, sizeof(ncaught));
  127. while (1) {
  128. #ifdef _WIN32
  129. n = recv(fd, signals, sizeof(signals), 0);
  130. #else
  131. n = read(fd, signals, sizeof(signals));
  132. #endif
  133. if (n == -1) {
  134. int err = evutil_socket_geterror(fd);
  135. if (! EVUTIL_ERR_RW_RETRIABLE(err))
  136. event_sock_err(1, fd, "%s: recv", __func__);
  137. break;
  138. } else if (n == 0) {
  139. /* XXX warn? */
  140. break;
  141. }
  142. for (i = 0; i < n; ++i) {
  143. ev_uint8_t sig = signals[i];
  144. if (sig < NSIG)
  145. ncaught[sig]++;
  146. }
  147. }
  148. EVBASE_ACQUIRE_LOCK(base, th_base_lock);
  149. for (i = 0; i < NSIG; ++i) {
  150. if (ncaught[i])
  151. evmap_signal_active_(base, i, ncaught[i]);
  152. }
  153. EVBASE_RELEASE_LOCK(base, th_base_lock);
  154. }
  155. int
  156. evsig_init_(struct event_base *base)
  157. {
  158. /*
  159. * Our signal handler is going to write to one end of the socket
  160. * pair to wake up our event loop. The event loop then scans for
  161. * signals that got delivered.
  162. */
  163. if (evutil_make_internal_pipe_(base->sig.ev_signal_pair) == -1) {
  164. #ifdef _WIN32
  165. /* Make this nonfatal on win32, where sometimes people
  166. have localhost firewalled. */
  167. event_sock_warn(-1, "%s: socketpair", __func__);
  168. #else
  169. event_sock_err(1, -1, "%s: socketpair", __func__);
  170. #endif
  171. return -1;
  172. }
  173. if (base->sig.sh_old) {
  174. mm_free(base->sig.sh_old);
  175. }
  176. base->sig.sh_old = NULL;
  177. base->sig.sh_old_max = 0;
  178. event_assign(&base->sig.ev_signal, base, base->sig.ev_signal_pair[0],
  179. EV_READ | EV_PERSIST, evsig_cb, base);
  180. base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL;
  181. event_priority_set(&base->sig.ev_signal, 0);
  182. base->evsigsel = &evsigops;
  183. return 0;
  184. }
  185. /* Helper: set the signal handler for evsignal to handler in base, so that
  186. * we can restore the original handler when we clear the current one. */
  187. int
  188. evsig_set_handler_(struct event_base *base,
  189. int evsignal, void (__cdecl *handler)(int))
  190. {
  191. #ifdef EVENT__HAVE_SIGACTION
  192. struct sigaction sa;
  193. #else
  194. ev_sighandler_t sh;
  195. #endif
  196. struct evsig_info *sig = &base->sig;
  197. void *p;
  198. /*
  199. * resize saved signal handler array up to the highest signal number.
  200. * a dynamic array is used to keep footprint on the low side.
  201. */
  202. if (evsignal >= sig->sh_old_max) {
  203. int new_max = evsignal + 1;
  204. event_debug(("%s: evsignal (%d) >= sh_old_max (%d), resizing",
  205. __func__, evsignal, sig->sh_old_max));
  206. p = mm_realloc(sig->sh_old, new_max * sizeof(*sig->sh_old));
  207. if (p == NULL) {
  208. event_warn("realloc");
  209. return (-1);
  210. }
  211. memset((char *)p + sig->sh_old_max * sizeof(*sig->sh_old),
  212. 0, (new_max - sig->sh_old_max) * sizeof(*sig->sh_old));
  213. sig->sh_old_max = new_max;
  214. sig->sh_old = p;
  215. }
  216. /* allocate space for previous handler out of dynamic array */
  217. sig->sh_old[evsignal] = mm_malloc(sizeof *sig->sh_old[evsignal]);
  218. if (sig->sh_old[evsignal] == NULL) {
  219. event_warn("malloc");
  220. return (-1);
  221. }
  222. /* save previous handler and setup new handler */
  223. #ifdef EVENT__HAVE_SIGACTION
  224. memset(&sa, 0, sizeof(sa));
  225. sa.sa_handler = handler;
  226. sa.sa_flags |= SA_RESTART;
  227. sigfillset(&sa.sa_mask);
  228. if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) {
  229. event_warn("sigaction");
  230. mm_free(sig->sh_old[evsignal]);
  231. sig->sh_old[evsignal] = NULL;
  232. return (-1);
  233. }
  234. #else
  235. if ((sh = signal(evsignal, handler)) == SIG_ERR) {
  236. event_warn("signal");
  237. mm_free(sig->sh_old[evsignal]);
  238. sig->sh_old[evsignal] = NULL;
  239. return (-1);
  240. }
  241. *sig->sh_old[evsignal] = sh;
  242. #endif
  243. return (0);
  244. }
  245. static int
  246. evsig_add(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p)
  247. {
  248. struct evsig_info *sig = &base->sig;
  249. (void)p;
  250. EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG);
  251. /* catch signals if they happen quickly */
  252. EVSIGBASE_LOCK();
  253. if (evsig_base != base && evsig_base_n_signals_added) {
  254. event_warnx("Added a signal to event base %p with signals "
  255. "already added to event_base %p. Only one can have "
  256. "signals at a time with the %s backend. The base with "
  257. "the most recently added signal or the most recent "
  258. "event_base_loop() call gets preference; do "
  259. "not rely on this behavior in future Libevent versions.",
  260. base, evsig_base, base->evsel->name);
  261. }
  262. evsig_base = base;
  263. evsig_base_n_signals_added = ++sig->ev_n_signals_added;
  264. evsig_base_fd = base->sig.ev_signal_pair[1];
  265. EVSIGBASE_UNLOCK();
  266. event_debug(("%s: %d: changing signal handler", __func__, (int)evsignal));
  267. if (evsig_set_handler_(base, (int)evsignal, evsig_handler) == -1) {
  268. goto err;
  269. }
  270. if (!sig->ev_signal_added) {
  271. if (event_add_nolock_(&sig->ev_signal, NULL, 0))
  272. goto err;
  273. sig->ev_signal_added = 1;
  274. }
  275. return (0);
  276. err:
  277. EVSIGBASE_LOCK();
  278. --evsig_base_n_signals_added;
  279. --sig->ev_n_signals_added;
  280. EVSIGBASE_UNLOCK();
  281. return (-1);
  282. }
  283. int
  284. evsig_restore_handler_(struct event_base *base, int evsignal)
  285. {
  286. int ret = 0;
  287. struct evsig_info *sig = &base->sig;
  288. #ifdef EVENT__HAVE_SIGACTION
  289. struct sigaction *sh;
  290. #else
  291. ev_sighandler_t *sh;
  292. #endif
  293. if (evsignal >= sig->sh_old_max) {
  294. /* Can't actually restore. */
  295. /* XXXX.*/
  296. return 0;
  297. }
  298. /* restore previous handler */
  299. sh = sig->sh_old[evsignal];
  300. sig->sh_old[evsignal] = NULL;
  301. #ifdef EVENT__HAVE_SIGACTION
  302. if (sigaction(evsignal, sh, NULL) == -1) {
  303. event_warn("sigaction");
  304. ret = -1;
  305. }
  306. #else
  307. if (signal(evsignal, *sh) == SIG_ERR) {
  308. event_warn("signal");
  309. ret = -1;
  310. }
  311. #endif
  312. mm_free(sh);
  313. return ret;
  314. }
  315. static int
  316. evsig_del(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p)
  317. {
  318. EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG);
  319. event_debug(("%s: "EV_SOCK_FMT": restoring signal handler",
  320. __func__, EV_SOCK_ARG(evsignal)));
  321. EVSIGBASE_LOCK();
  322. --evsig_base_n_signals_added;
  323. --base->sig.ev_n_signals_added;
  324. EVSIGBASE_UNLOCK();
  325. return (evsig_restore_handler_(base, (int)evsignal));
  326. }
  327. static void __cdecl
  328. evsig_handler(int sig)
  329. {
  330. int save_errno = errno;
  331. #ifdef _WIN32
  332. int socket_errno = EVUTIL_SOCKET_ERROR();
  333. #endif
  334. ev_uint8_t msg;
  335. if (evsig_base == NULL) {
  336. event_warnx(
  337. "%s: received signal %d, but have no base configured",
  338. __func__, sig);
  339. return;
  340. }
  341. #ifndef EVENT__HAVE_SIGACTION
  342. signal(sig, evsig_handler);
  343. #endif
  344. /* Wake up our notification mechanism */
  345. msg = sig;
  346. #ifdef _WIN32
  347. send(evsig_base_fd, (char*)&msg, 1, 0);
  348. #else
  349. {
  350. int r = write(evsig_base_fd, (char*)&msg, 1);
  351. (void)r; /* Suppress 'unused return value' and 'unused var' */
  352. }
  353. #endif
  354. errno = save_errno;
  355. #ifdef _WIN32
  356. EVUTIL_SET_SOCKET_ERROR(socket_errno);
  357. #endif
  358. }
  359. void
  360. evsig_dealloc_(struct event_base *base)
  361. {
  362. int i = 0;
  363. if (base->sig.ev_signal_added) {
  364. event_del(&base->sig.ev_signal);
  365. base->sig.ev_signal_added = 0;
  366. }
  367. /* debug event is created in evsig_init_/event_assign even when
  368. * ev_signal_added == 0, so unassign is required */
  369. event_debug_unassign(&base->sig.ev_signal);
  370. for (i = 0; i < NSIG; ++i) {
  371. if (i < base->sig.sh_old_max && base->sig.sh_old[i] != NULL)
  372. evsig_restore_handler_(base, i);
  373. }
  374. EVSIGBASE_LOCK();
  375. if (base == evsig_base) {
  376. evsig_base = NULL;
  377. evsig_base_n_signals_added = 0;
  378. evsig_base_fd = -1;
  379. }
  380. EVSIGBASE_UNLOCK();
  381. if (base->sig.ev_signal_pair[0] != -1) {
  382. evutil_closesocket(base->sig.ev_signal_pair[0]);
  383. base->sig.ev_signal_pair[0] = -1;
  384. }
  385. if (base->sig.ev_signal_pair[1] != -1) {
  386. evutil_closesocket(base->sig.ev_signal_pair[1]);
  387. base->sig.ev_signal_pair[1] = -1;
  388. }
  389. base->sig.sh_old_max = 0;
  390. /* per index frees are handled in evsig_del() */
  391. if (base->sig.sh_old) {
  392. mm_free(base->sig.sh_old);
  393. base->sig.sh_old = NULL;
  394. }
  395. }
  396. static void
  397. evsig_free_globals_locks(void)
  398. {
  399. #ifndef EVENT__DISABLE_THREAD_SUPPORT
  400. if (evsig_base_lock != NULL) {
  401. EVTHREAD_FREE_LOCK(evsig_base_lock, 0);
  402. evsig_base_lock = NULL;
  403. }
  404. #endif
  405. return;
  406. }
  407. void
  408. evsig_free_globals_(void)
  409. {
  410. evsig_free_globals_locks();
  411. }
  412. #ifndef EVENT__DISABLE_THREAD_SUPPORT
  413. int
  414. evsig_global_setup_locks_(const int enable_locks)
  415. {
  416. EVTHREAD_SETUP_GLOBAL_LOCK(evsig_base_lock, 0);
  417. return 0;
  418. }
  419. #endif