Browse Source

*** empty log message ***

master
Marc Alexander Lehmann 10 years ago
parent
commit
41d4c3b76d
  1. 4
      Changes
  2. 32
      ev.c
  3. 9
      ev.h
  4. 58
      ev.pod
  5. 3
      ev_vars.h
  6. 4
      ev_wrap.h

4
Changes

@ -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

32
ev.c

@ -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
}

9
ev.h

@ -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);

58
ev.pod

@ -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

3
ev_vars.h

@ -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 */

4
ev_wrap.h

@ -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

Loading…
Cancel
Save