diff options
| author | root <root> | 2011-01-10 01:58:54 +0000 | 
|---|---|---|
| committer | root <root> | 2011-01-10 01:58:54 +0000 | 
| commit | fdf8e637ed5779a72783db49d403f4f8b2e76de0 (patch) | |
| tree | 4269b403eae4c81717b29963e66ce01eb3b9ec39 | |
| parent | f1c5ab398807a485aff4f2b412b8974fe7f62d0f (diff) | |
*** empty log message ***
| -rw-r--r-- | Changes | 4 | ||||
| -rw-r--r-- | ev.c | 32 | ||||
| -rw-r--r-- | ev.h | 9 | ||||
| -rw-r--r-- | ev.pod | 58 | ||||
| -rw-r--r-- | ev_vars.h | 3 | ||||
| -rw-r--r-- | ev_wrap.h | 4 | 
6 files changed, 93 insertions, 17 deletions
@@ -3,13 +3,15 @@ Revision history for libev, a high-performance and full-featured event loop.  TODO: move some other examples to common idioms? combining watchers,  thread usage, coroutine switch? -TODO: /dev/null epoll breakage, maybe catch EPERM?  TODO: frankenpoll  4.03  	- support files, /dev/zero etc. the same way as select in the epoll            backend, by generating events on our own.  	- define EV_READ/EV_WRITE as macros in event.h, as some programs use            #ifdef to test for them. +        - new (experimental) function: ev_feed_signal. +        - new (to become default) EVFLAG_NOSIGMASK flag. +        - new EVBACKEND_MASK symbol.  4.01 Fri Nov  5 21:51:29 CET 2010          - automake fucked it up, apparently, --add-missing -f is not quite enough @@ -1,7 +1,7 @@  /*   * libev event processing core, watcher management   * - * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de> + * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without modifica- @@ -1371,19 +1371,28 @@ pipecb (EV_P_ ev_io *iow, int revents)  /*****************************************************************************/ -static void -ev_sighandler (int signum) +void +ev_feed_signal (int signum)  {  #if EV_MULTIPLICITY    EV_P = signals [signum - 1].loop; + +  if (!EV_A) +    return;  #endif +  signals [signum - 1].pending = 1; +  evpipe_write (EV_A_ &sig_pending); +} + +static void +ev_sighandler (int signum) +{  #ifdef _WIN32    signal (signum, ev_sighandler);  #endif -  signals [signum - 1].pending = 1; -  evpipe_write (EV_A_ &sig_pending); +  ev_feed_signal (signum);  }  void noinline @@ -1645,6 +1654,8 @@ loop_init (EV_P_ unsigned int flags)  {    if (!backend)      { +      origflags = flags; +  #if EV_USE_REALTIME        if (!have_realtime)          { @@ -1699,7 +1710,7 @@ loop_init (EV_P_ unsigned int flags)        sigfd             = flags & EVFLAG_SIGNALFD  ? -2 : -1;  #endif -      if (!(flags & 0x0000ffffU)) +      if (!(flags & EVBACKEND_MASK))          flags |= ev_recommended_backends ();  #if EV_USE_IOCP @@ -2881,9 +2892,12 @@ ev_signal_start (EV_P_ ev_signal *w)          sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */          sigaction (w->signum, &sa, 0); -        sigemptyset (&sa.sa_mask); -        sigaddset (&sa.sa_mask, w->signum); -        sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0); +        if (origflags & EVFLAG_NOSIGMASK) +          { +            sigemptyset (&sa.sa_mask); +            sigaddset (&sa.sa_mask, w->signum); +            sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0); +          }  #endif        } @@ -1,7 +1,7 @@  /*   * libev native API header   * - * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de> + * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without modifica- @@ -491,7 +491,8 @@ enum {  #if EV_COMPAT3    EVFLAG_NOSIGFD   = 0, /* compatibility to pre-3.9 */  #endif -  EVFLAG_SIGNALFD  = 0x00200000U  /* attempt to use signalfd */ +  EVFLAG_SIGNALFD  = 0x00200000U, /* attempt to use signalfd */ +  EVFLAG_NOSIGMASK = 0x00400000U  /* avoid modifying the signal mask */  };  /* method bits to be ored together */ @@ -502,7 +503,8 @@ enum {    EVBACKEND_KQUEUE  = 0x00000008U, /* bsd */    EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /* NYI */    EVBACKEND_PORT    = 0x00000020U, /* solaris 10 */ -  EVBACKEND_ALL     = 0x0000003FU +  EVBACKEND_ALL     = 0x0000003FU, /* all known backends */ +  EVBACKEND_MASK    = 0x0000FFFFU  /* all future backends */  };  #if EV_PROTOTYPES @@ -720,6 +722,7 @@ void ev_resume  (EV_P);  void ev_feed_event     (EV_P_ void *w, int revents);  void ev_feed_fd_event  (EV_P_ int fd, int revents);  #if EV_SIGNAL_ENABLE +void ev_feed_signal    (int signum);  void ev_feed_signal_event (EV_P_ int signum);  #endif  void ev_invoke         (EV_P_ void *w, int revents); @@ -301,6 +301,19 @@ Example: This is basically the same thing that libev does internally, too.     ...     ev_set_syserr_cb (fatal_error); +=item ev_feed_signal (int signum) + +This function can be used to "simulate" a signal receive. It is completely +safe to call this function at any time, from any context, including signal +handlers or random threads. + +It's main use is to customise signal handling in your process, especially +in the presence of threads. For example, you could block signals +by default in all threads (and specifying C<EVFLAG_NOSIGMASK> when +creating any loops), and in one thread, use C<sigwait> or any other +mechanism to wait for signals, then "deliver" them to libev by calling +C<ev_feed_signal>. +  =back  =head1 FUNCTIONS CONTROLLING EVENT LOOPS @@ -421,6 +434,18 @@ Signalfd will not be used by default as this changes your signal mask, and  there are a lot of shoddy libraries and programs (glib's threadpool for  example) that can't properly initialise their signal masks. +=item C<EVFLAG_NOSIGMASK> + +When this flag is specified, then libev will avoid to modify the signal +mask. Specifically, this means you ahve to make sure signals are unblocked +when you want to receive them. + +This behaviour is useful when you want to do your own signal handling, or +want to handle signals only in specific threads and want to avoid libev +unblocking the signals. + +This flag's behaviour will become the default in future versions of libev. +  =item C<EVBACKEND_SELECT>  (value 1, portable select backend)  This is your standard select(2) backend. Not I<completely> standard, as @@ -582,7 +607,15 @@ Try all backends (even potentially broken ones that wouldn't be tried  with C<EVFLAG_AUTO>). Since this is a mask, you can do stuff such as  C<EVBACKEND_ALL & ~EVBACKEND_KQUEUE>. -It is definitely not recommended to use this flag. +It is definitely not recommended to use this flag, use whatever +C<ev_recommended_backends ()> returns, or simply do not specify a backend +at all. + +=item C<EVBACKEND_MASK> + +Not a backend at all, but a mask to select all backend bits from a +C<flags> value, in case you want to mask out any backends from a flags +value (e.g. when modifying the C<LIBEV_FLAGS> environment variable).  =back @@ -2322,6 +2355,20 @@ So I can't stress this enough: I<If you do not reset your signal mask when  you expect it to be empty, you have a race condition in your code>. This  is not a libev-specific thing, this is true for most event libraries. +=head3 The special problem of threads signal handling + +POSIX threads has problematic signal handling semantics, specifically, +a lot of functionality (sigfd, sigwait etc.) only really works if all +threads in a process block signals, which is hard to achieve. + +When you want to use sigwait (or mix libev signal handling with your own +for the same signals), you can tackle this problem by globally blocking +all signals before creating any threads (or creating them with a fully set +sigprocmask) and also specifying the C<EVFLAG_NOSIGMASK> when creating +loops. Then designate one thread as "signal receiver thread" which handles +these signals. You can pass on any signals that libev might be interested +in by calling C<ev_feed_signal>. +  =head3 Watcher-Specific Functions and Data Members  =over 4 @@ -3177,7 +3224,10 @@ it by calling C<ev_async_send>, which is thread- and signal safe.  This functionality is very similar to C<ev_signal> watchers, as signals,  too, are asynchronous in nature, and signals, too, will be compressed  (i.e. the number of callback invocations may be less than the number of -C<ev_async_sent> calls). +C<ev_async_sent> calls). In fact, you could use signal watchers as a kind +of "global async watchers" by using a watcher on an otherwise unused +signal, and C<ev_feed_signal> to signal this watcher from another thread, +even without knowing which loop owns the signal.  Unlike C<ev_signal> watchers, C<ev_async> works with any event loop, not  just the default loop. @@ -3363,8 +3413,8 @@ the given events it.  =item ev_feed_signal_event (loop, int signum) -Feed an event as if the given signal occurred (C<loop> must be the default -loop!). +Feed an event as if the given signal occurred. See also C<ev_feed_signal>, +which is async-safe.  =back @@ -180,12 +180,15 @@ VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE])  #endif  VARx(EV_ATOMIC_T, sig_pending) +VARx(int, nosigmask)  #if EV_USE_SIGNALFD || EV_GENWRAP  VARx(int, sigfd)  VARx(ev_io, sigfd_w)  VARx(sigset_t, sigfd_set)  #endif +VARx(unsigned int, origflags) /* original loop flags */ +  #if EV_FEATURE_API || EV_GENWRAP  VARx(unsigned int, loop_count) /* total number of loop iterations/blocks */  VARx(unsigned int, loop_depth) /* #ev_run enters - #ev_run leaves */ @@ -85,9 +85,11 @@  #define fs_2625 ((loop)->fs_2625)  #define fs_hash ((loop)->fs_hash)  #define sig_pending ((loop)->sig_pending) +#define nosigmask ((loop)->nosigmask)  #define sigfd ((loop)->sigfd)  #define sigfd_w ((loop)->sigfd_w)  #define sigfd_set ((loop)->sigfd_set) +#define origflags ((loop)->origflags)  #define loop_count ((loop)->loop_count)  #define loop_depth ((loop)->loop_depth)  #define userdata ((loop)->userdata) @@ -180,9 +182,11 @@  #undef fs_2625  #undef fs_hash  #undef sig_pending +#undef nosigmask  #undef sigfd  #undef sigfd_w  #undef sigfd_set +#undef origflags  #undef loop_count  #undef loop_depth  #undef userdata  | 
