This source file includes following definitions.
- evsig_set_base
- evsig_cb
- evsig_init
- _evsig_set_handler
- evsig_add
- _evsig_restore_handler
- evsig_del
- evsig_handler
- evsig_dealloc
- evsig_global_setup_locks_
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 #include "event2/event-config.h"
  30 
  31 #ifdef WIN32
  32 #define WIN32_LEAN_AND_MEAN
  33 #include <winsock2.h>
  34 #include <windows.h>
  35 #undef WIN32_LEAN_AND_MEAN
  36 #endif
  37 #include <sys/types.h>
  38 #ifdef _EVENT_HAVE_SYS_TIME_H
  39 #include <sys/time.h>
  40 #endif
  41 #include <sys/queue.h>
  42 #ifdef _EVENT_HAVE_SYS_SOCKET_H
  43 #include <sys/socket.h>
  44 #endif
  45 #include <signal.h>
  46 #include <stdio.h>
  47 #include <stdlib.h>
  48 #include <string.h>
  49 #ifdef _EVENT_HAVE_UNISTD_H
  50 #include <unistd.h>
  51 #endif
  52 #include <errno.h>
  53 #ifdef _EVENT_HAVE_FCNTL_H
  54 #include <fcntl.h>
  55 #endif
  56 
  57 #include "event2/event.h"
  58 #include "event2/event_struct.h"
  59 #include "event-internal.h"
  60 #include "event2/util.h"
  61 #include "evsignal-internal.h"
  62 #include "log-internal.h"
  63 #include "evmap-internal.h"
  64 #include "evthread-internal.h"
  65 
  66 
  67 
  68 
  69 
  70 
  71 
  72 
  73 
  74 
  75 
  76 
  77 
  78 
  79 
  80 
  81 
  82 
  83 
  84 #ifndef WIN32
  85 
  86 
  87 #define __cdecl
  88 #endif
  89 
  90 static int evsig_add(struct event_base *, evutil_socket_t, short, short, void *);
  91 static int evsig_del(struct event_base *, evutil_socket_t, short, short, void *);
  92 
  93 static const struct eventop evsigops = {
  94         "signal",
  95         NULL,
  96         evsig_add,
  97         evsig_del,
  98         NULL,
  99         NULL,
 100         0, 0, 0
 101 };
 102 
 103 #ifndef _EVENT_DISABLE_THREAD_SUPPORT
 104 
 105 static void *evsig_base_lock = NULL;
 106 #endif
 107 
 108 static struct event_base *evsig_base = NULL;
 109 
 110 static int evsig_base_n_signals_added = 0;
 111 static evutil_socket_t evsig_base_fd = -1;
 112 
 113 static void __cdecl evsig_handler(int sig);
 114 
 115 #define EVSIGBASE_LOCK() EVLOCK_LOCK(evsig_base_lock, 0)
 116 #define EVSIGBASE_UNLOCK() EVLOCK_UNLOCK(evsig_base_lock, 0)
 117 
 118 void
 119 evsig_set_base(struct event_base *base)
 120 {
 121         EVSIGBASE_LOCK();
 122         evsig_base = base;
 123         evsig_base_n_signals_added = base->sig.ev_n_signals_added;
 124         evsig_base_fd = base->sig.ev_signal_pair[0];
 125         EVSIGBASE_UNLOCK();
 126 }
 127 
 128 
 129 static void
 130 evsig_cb(evutil_socket_t fd, short what, void *arg)
 131 {
 132         static char signals[1024];
 133         ev_ssize_t n;
 134         int i;
 135         int ncaught[NSIG];
 136         struct event_base *base;
 137 
 138         base = arg;
 139 
 140         memset(&ncaught, 0, sizeof(ncaught));
 141 
 142         while (1) {
 143                 n = recv(fd, signals, sizeof(signals), 0);
 144                 if (n == -1) {
 145                         int err = evutil_socket_geterror(fd);
 146                         if (! EVUTIL_ERR_RW_RETRIABLE(err))
 147                                 event_sock_err(1, fd, "%s: recv", __func__);
 148                         break;
 149                 } else if (n == 0) {
 150                         
 151                         break;
 152                 }
 153                 for (i = 0; i < n; ++i) {
 154                         ev_uint8_t sig = signals[i];
 155                         if (sig < NSIG)
 156                                 ncaught[sig]++;
 157                 }
 158         }
 159 
 160         EVBASE_ACQUIRE_LOCK(base, th_base_lock);
 161         for (i = 0; i < NSIG; ++i) {
 162                 if (ncaught[i])
 163                         evmap_signal_active(base, i, ncaught[i]);
 164         }
 165         EVBASE_RELEASE_LOCK(base, th_base_lock);
 166 }
 167 
 168 int
 169 evsig_init(struct event_base *base)
 170 {
 171         
 172 
 173 
 174 
 175 
 176         if (evutil_socketpair(
 177                     AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1) {
 178 #ifdef WIN32
 179                 
 180 
 181                 event_sock_warn(-1, "%s: socketpair", __func__);
 182 #else
 183                 event_sock_err(1, -1, "%s: socketpair", __func__);
 184 #endif
 185                 return -1;
 186         }
 187 
 188         evutil_make_socket_closeonexec(base->sig.ev_signal_pair[0]);
 189         evutil_make_socket_closeonexec(base->sig.ev_signal_pair[1]);
 190         base->sig.sh_old = NULL;
 191         base->sig.sh_old_max = 0;
 192 
 193         evutil_make_socket_nonblocking(base->sig.ev_signal_pair[0]);
 194         evutil_make_socket_nonblocking(base->sig.ev_signal_pair[1]);
 195 
 196         event_assign(&base->sig.ev_signal, base, base->sig.ev_signal_pair[1],
 197                 EV_READ | EV_PERSIST, evsig_cb, base);
 198 
 199         base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL;
 200         event_priority_set(&base->sig.ev_signal, 0);
 201 
 202         base->evsigsel = &evsigops;
 203 
 204         return 0;
 205 }
 206 
 207 
 208 
 209 int
 210 _evsig_set_handler(struct event_base *base,
 211     int evsignal, void (__cdecl *handler)(int))
 212 {
 213 #ifdef _EVENT_HAVE_SIGACTION
 214         struct sigaction sa;
 215 #else
 216         ev_sighandler_t sh;
 217 #endif
 218         struct evsig_info *sig = &base->sig;
 219         void *p;
 220 
 221         
 222 
 223 
 224 
 225         if (evsignal >= sig->sh_old_max) {
 226                 int new_max = evsignal + 1;
 227                 event_debug(("%s: evsignal (%d) >= sh_old_max (%d), resizing",
 228                             __func__, evsignal, sig->sh_old_max));
 229                 p = mm_realloc(sig->sh_old, new_max * sizeof(*sig->sh_old));
 230                 if (p == NULL) {
 231                         event_warn("realloc");
 232                         return (-1);
 233                 }
 234 
 235                 memset((char *)p + sig->sh_old_max * sizeof(*sig->sh_old),
 236                     0, (new_max - sig->sh_old_max) * sizeof(*sig->sh_old));
 237 
 238                 sig->sh_old_max = new_max;
 239                 sig->sh_old = p;
 240         }
 241 
 242         
 243         sig->sh_old[evsignal] = mm_malloc(sizeof *sig->sh_old[evsignal]);
 244         if (sig->sh_old[evsignal] == NULL) {
 245                 event_warn("malloc");
 246                 return (-1);
 247         }
 248 
 249         
 250 #ifdef _EVENT_HAVE_SIGACTION
 251         memset(&sa, 0, sizeof(sa));
 252         sa.sa_handler = handler;
 253         sa.sa_flags |= SA_RESTART;
 254         sigfillset(&sa.sa_mask);
 255 
 256         if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) {
 257                 event_warn("sigaction");
 258                 mm_free(sig->sh_old[evsignal]);
 259                 sig->sh_old[evsignal] = NULL;
 260                 return (-1);
 261         }
 262 #else
 263         if ((sh = signal(evsignal, handler)) == SIG_ERR) {
 264                 event_warn("signal");
 265                 mm_free(sig->sh_old[evsignal]);
 266                 sig->sh_old[evsignal] = NULL;
 267                 return (-1);
 268         }
 269         *sig->sh_old[evsignal] = sh;
 270 #endif
 271 
 272         return (0);
 273 }
 274 
 275 static int
 276 evsig_add(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p)
 277 {
 278         struct evsig_info *sig = &base->sig;
 279         (void)p;
 280 
 281         EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG);
 282 
 283         
 284         EVSIGBASE_LOCK();
 285         if (evsig_base != base && evsig_base_n_signals_added) {
 286                 event_warnx("Added a signal to event base %p with signals "
 287                     "already added to event_base %p.  Only one can have "
 288                     "signals at a time with the %s backend.  The base with "
 289                     "the most recently added signal or the most recent "
 290                     "event_base_loop() call gets preference; do "
 291                     "not rely on this behavior in future Libevent versions.",
 292                     base, evsig_base, base->evsel->name);
 293         }
 294         evsig_base = base;
 295         evsig_base_n_signals_added = ++sig->ev_n_signals_added;
 296         evsig_base_fd = base->sig.ev_signal_pair[0];
 297         EVSIGBASE_UNLOCK();
 298 
 299         event_debug(("%s: %d: changing signal handler", __func__, (int)evsignal));
 300         if (_evsig_set_handler(base, (int)evsignal, evsig_handler) == -1) {
 301                 goto err;
 302         }
 303 
 304 
 305         if (!sig->ev_signal_added) {
 306                 if (event_add(&sig->ev_signal, NULL))
 307                         goto err;
 308                 sig->ev_signal_added = 1;
 309         }
 310 
 311         return (0);
 312 
 313 err:
 314         EVSIGBASE_LOCK();
 315         --evsig_base_n_signals_added;
 316         --sig->ev_n_signals_added;
 317         EVSIGBASE_UNLOCK();
 318         return (-1);
 319 }
 320 
 321 int
 322 _evsig_restore_handler(struct event_base *base, int evsignal)
 323 {
 324         int ret = 0;
 325         struct evsig_info *sig = &base->sig;
 326 #ifdef _EVENT_HAVE_SIGACTION
 327         struct sigaction *sh;
 328 #else
 329         ev_sighandler_t *sh;
 330 #endif
 331 
 332         
 333         sh = sig->sh_old[evsignal];
 334         sig->sh_old[evsignal] = NULL;
 335 #ifdef _EVENT_HAVE_SIGACTION
 336         if (sigaction(evsignal, sh, NULL) == -1) {
 337                 event_warn("sigaction");
 338                 ret = -1;
 339         }
 340 #else
 341         if (signal(evsignal, *sh) == SIG_ERR) {
 342                 event_warn("signal");
 343                 ret = -1;
 344         }
 345 #endif
 346 
 347         mm_free(sh);
 348 
 349         return ret;
 350 }
 351 
 352 static int
 353 evsig_del(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p)
 354 {
 355         EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG);
 356 
 357         event_debug(("%s: "EV_SOCK_FMT": restoring signal handler",
 358                 __func__, EV_SOCK_ARG(evsignal)));
 359 
 360         EVSIGBASE_LOCK();
 361         --evsig_base_n_signals_added;
 362         --base->sig.ev_n_signals_added;
 363         EVSIGBASE_UNLOCK();
 364 
 365         return (_evsig_restore_handler(base, (int)evsignal));
 366 }
 367 
 368 static void __cdecl
 369 evsig_handler(int sig)
 370 {
 371         int save_errno = errno;
 372 #ifdef WIN32
 373         int socket_errno = EVUTIL_SOCKET_ERROR();
 374 #endif
 375         ev_uint8_t msg;
 376 
 377         if (evsig_base == NULL) {
 378                 event_warnx(
 379                         "%s: received signal %d, but have no base configured",
 380                         __func__, sig);
 381                 return;
 382         }
 383 
 384 #ifndef _EVENT_HAVE_SIGACTION
 385         signal(sig, evsig_handler);
 386 #endif
 387 
 388         
 389         msg = sig;
 390         send(evsig_base_fd, (char*)&msg, 1, 0);
 391         errno = save_errno;
 392 #ifdef WIN32
 393         EVUTIL_SET_SOCKET_ERROR(socket_errno);
 394 #endif
 395 }
 396 
 397 void
 398 evsig_dealloc(struct event_base *base)
 399 {
 400         int i = 0;
 401         if (base->sig.ev_signal_added) {
 402                 event_del(&base->sig.ev_signal);
 403                 base->sig.ev_signal_added = 0;
 404         }
 405         
 406 
 407         event_debug_unassign(&base->sig.ev_signal);
 408 
 409         for (i = 0; i < NSIG; ++i) {
 410                 if (i < base->sig.sh_old_max && base->sig.sh_old[i] != NULL)
 411                         _evsig_restore_handler(base, i);
 412         }
 413         EVSIGBASE_LOCK();
 414         if (base == evsig_base) {
 415                 evsig_base = NULL;
 416                 evsig_base_n_signals_added = 0;
 417                 evsig_base_fd = -1;
 418         }
 419         EVSIGBASE_UNLOCK();
 420 
 421         if (base->sig.ev_signal_pair[0] != -1) {
 422                 evutil_closesocket(base->sig.ev_signal_pair[0]);
 423                 base->sig.ev_signal_pair[0] = -1;
 424         }
 425         if (base->sig.ev_signal_pair[1] != -1) {
 426                 evutil_closesocket(base->sig.ev_signal_pair[1]);
 427                 base->sig.ev_signal_pair[1] = -1;
 428         }
 429         base->sig.sh_old_max = 0;
 430 
 431         
 432         if (base->sig.sh_old) {
 433                 mm_free(base->sig.sh_old);
 434                 base->sig.sh_old = NULL;
 435         }
 436 }
 437 
 438 #ifndef _EVENT_DISABLE_THREAD_SUPPORT
 439 int
 440 evsig_global_setup_locks_(const int enable_locks)
 441 {
 442         EVTHREAD_SETUP_GLOBAL_LOCK(evsig_base_lock, 0);
 443         return 0;
 444 }
 445 #endif