A clone of btpd with my configuration changes.
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

signal.c 5.1 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
  2. /*
  3. * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
  4. * All rights reserved.
  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. #ifdef HAVE_CONFIG_H
  29. #include "config.h"
  30. #endif
  31. #include <sys/types.h>
  32. #ifdef HAVE_SYS_TIME_H
  33. #include <sys/time.h>
  34. #else
  35. #include <sys/_time.h>
  36. #endif
  37. #include <sys/queue.h>
  38. #include <sys/socket.h>
  39. #include <signal.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43. #include <unistd.h>
  44. #include <errno.h>
  45. #ifdef HAVE_FCNTL_H
  46. #include <fcntl.h>
  47. #endif
  48. #include "event.h"
  49. #include "evsignal.h"
  50. #include "log.h"
  51. extern struct event_list signalqueue;
  52. static sig_atomic_t evsigcaught[NSIG];
  53. static int needrecalc;
  54. volatile sig_atomic_t evsignal_caught = 0;
  55. static struct event ev_signal;
  56. static int ev_signal_pair[2];
  57. static int ev_signal_added;
  58. /* Callback for when the signal handler write a byte to our signaling socket */
  59. static void
  60. evsignal_cb(int fd, short what, void *arg)
  61. {
  62. static char signals[100];
  63. struct event *ev = arg;
  64. ssize_t n;
  65. n = read(fd, signals, sizeof(signals));
  66. if (n == -1)
  67. event_err(1, "%s: read", __func__);
  68. event_add(ev, NULL);
  69. }
  70. #ifdef HAVE_SETFD
  71. #define FD_CLOSEONEXEC(x) do { \
  72. if (fcntl(x, F_SETFD, 1) == -1) \
  73. event_warn("fcntl(%d, F_SETFD)", x); \
  74. } while (0)
  75. #else
  76. #define FD_CLOSEONEXEC(x)
  77. #endif
  78. void
  79. evsignal_init(sigset_t *evsigmask)
  80. {
  81. sigemptyset(evsigmask);
  82. /*
  83. * Our signal handler is going to write to one end of the socket
  84. * pair to wake up our event loop. The event loop then scans for
  85. * signals that got delivered.
  86. */
  87. if (socketpair(AF_UNIX, SOCK_STREAM, 0, ev_signal_pair) == -1)
  88. event_err(1, "%s: socketpair", __func__);
  89. FD_CLOSEONEXEC(ev_signal_pair[0]);
  90. FD_CLOSEONEXEC(ev_signal_pair[1]);
  91. fcntl(ev_signal_pair[0], F_SETFL, O_NONBLOCK);
  92. event_set(&ev_signal, ev_signal_pair[1], EV_READ,
  93. evsignal_cb, &ev_signal);
  94. ev_signal.ev_flags |= EVLIST_INTERNAL;
  95. }
  96. int
  97. evsignal_add(sigset_t *evsigmask, struct event *ev)
  98. {
  99. int evsignal;
  100. if (ev->ev_events & (EV_READ|EV_WRITE))
  101. event_errx(1, "%s: EV_SIGNAL incompatible use", __func__);
  102. evsignal = EVENT_SIGNAL(ev);
  103. sigaddset(evsigmask, evsignal);
  104. return (0);
  105. }
  106. /*
  107. * Nothing to be done here.
  108. */
  109. int
  110. evsignal_del(sigset_t *evsigmask, struct event *ev)
  111. {
  112. int evsignal;
  113. evsignal = EVENT_SIGNAL(ev);
  114. sigdelset(evsigmask, evsignal);
  115. needrecalc = 1;
  116. return (sigaction(EVENT_SIGNAL(ev),(struct sigaction *)SIG_DFL, NULL));
  117. }
  118. static void
  119. evsignal_handler(int sig)
  120. {
  121. int save_errno = errno;
  122. evsigcaught[sig]++;
  123. evsignal_caught = 1;
  124. /* Wake up our notification mechanism */
  125. write(ev_signal_pair[0], "a", 1);
  126. errno = save_errno;
  127. }
  128. int
  129. evsignal_recalc(sigset_t *evsigmask)
  130. {
  131. struct sigaction sa;
  132. struct event *ev;
  133. if (!ev_signal_added) {
  134. ev_signal_added = 1;
  135. event_add(&ev_signal, NULL);
  136. }
  137. if (TAILQ_FIRST(&signalqueue) == NULL && !needrecalc)
  138. return (0);
  139. needrecalc = 0;
  140. if (sigprocmask(SIG_BLOCK, evsigmask, NULL) == -1)
  141. return (-1);
  142. /* Reinstall our signal handler. */
  143. memset(&sa, 0, sizeof(sa));
  144. sa.sa_handler = evsignal_handler;
  145. sa.sa_mask = *evsigmask;
  146. sa.sa_flags |= SA_RESTART;
  147. TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
  148. if (sigaction(EVENT_SIGNAL(ev), &sa, NULL) == -1)
  149. return (-1);
  150. }
  151. return (0);
  152. }
  153. int
  154. evsignal_deliver(sigset_t *evsigmask)
  155. {
  156. if (TAILQ_FIRST(&signalqueue) == NULL)
  157. return (0);
  158. return (sigprocmask(SIG_UNBLOCK, evsigmask, NULL));
  159. /* XXX - pending signals handled here */
  160. }
  161. void
  162. evsignal_process(void)
  163. {
  164. struct event *ev;
  165. sig_atomic_t ncalls;
  166. TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
  167. ncalls = evsigcaught[EVENT_SIGNAL(ev)];
  168. if (ncalls) {
  169. if (!(ev->ev_events & EV_PERSIST))
  170. event_del(ev);
  171. event_active(ev, EV_SIGNAL, ncalls);
  172. }
  173. }
  174. memset(evsigcaught, 0, sizeof(evsigcaught));
  175. evsignal_caught = 0;
  176. }