signal support

master
Marc Alexander Lehmann 2007-10-31 00:24:16 +00:00
parent 5215d15135
commit 3c94f216f6
4 changed files with 126 additions and 26 deletions

9
README
View File

@ -1,7 +1,8 @@
libev is modelled after libevent (http://monkey.org/~provos/libevent/), but aims
to be faster and more correct, and also more featureful. Examples:
- multiple watchers can wait for the same event without deregistering others.
- multiple watchers can wait for the same event without deregistering others,
both for file descriptors as well as signals.
(registering two read events on fd 10 and unregistering one will not
break the other)
@ -56,7 +57,9 @@ whats missing?
- evdns, evhttp, bufferevent are missing, libev is only an even library at
the moment.
- no priority support at the moment.
- no priority support at the moment
- kqueue, poll (libev currently implements epoll and select).
- kqueue, poll (libev currently implements epoll and select)
- windows support (whats windows?)

126
ev.c
View File

@ -1,5 +1,8 @@
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
@ -181,14 +184,73 @@ downheap (struct ev_timer **timers, int N, int k)
timers [k]->active = k + 1;
}
static struct ev_signal **signals;
typedef struct
{
struct ev_signal *head;
sig_atomic_t gotsig;
} ANSIG;
static ANSIG *signals;
static int signalmax;
static int sigpipe [2];
static sig_atomic_t gotsig;
static struct ev_io sigev;
static void
signals_init (struct ev_signal **base, int count)
signals_init (ANSIG *base, int count)
{
while (count--)
*base++ = 0;
{
base->head = 0;
base->gotsig = 0;
++base;
}
}
static void
sighandler (int signum)
{
signals [signum - 1].gotsig = 1;
if (!gotsig)
{
gotsig = 1;
write (sigpipe [1], &gotsig, 1);
}
}
static void
sigcb (struct ev_io *iow, int revents)
{
struct ev_signal *w;
int sig;
gotsig = 0;
read (sigpipe [0], &revents, 1);
for (sig = signalmax; sig--; )
if (signals [sig].gotsig)
{
signals [sig].gotsig = 0;
for (w = signals [sig].head; w; w = w->next)
event ((struct ev_watcher *)w, EV_SIGNAL);
}
}
static void
siginit (void)
{
fcntl (sigpipe [0], F_SETFD, FD_CLOEXEC);
fcntl (sigpipe [1], F_SETFD, FD_CLOEXEC);
/* rather than sort out wether we really need nb, set it */
fcntl (sigpipe [0], F_SETFL, O_NONBLOCK);
fcntl (sigpipe [1], F_SETFL, O_NONBLOCK);
evio_set (&sigev, sigpipe [0], EV_READ);
evio_start (&sigev);
}
#if HAVE_EPOLL
@ -212,16 +274,23 @@ int ev_init (int flags)
now = get_clock ();
diff = ev_now - now;
#if HAVE_EPOLL
if (epoll_init (flags))
return ev_method;
#endif
#if HAVE_SELECT
if (select_init (flags))
return ev_method;
#endif
if (pipe (sigpipe))
return 0;
ev_method = EVMETHOD_NONE;
#if HAVE_EPOLL
if (ev_method == EVMETHOD_NONE) epoll_init (flags);
#endif
#if HAVE_SELECT
if (ev_method == EVMETHOD_NONE) select_init (flags);
#endif
if (ev_method)
{
evw_init (&sigev, sigcb, 0);
siginit ();
}
return ev_method;
}
@ -239,6 +308,12 @@ void ev_postfork_child (void)
if (ev_method == EVMETHOD_EPOLL)
epoll_postfork_child ();
#endif
evio_stop (&sigev);
close (sigpipe [0]);
close (sigpipe [1]);
pipe (sigpipe);
siginit ();
}
static void
@ -538,7 +613,16 @@ evsignal_start (struct ev_signal *w)
ev_start ((struct ev_watcher *)w, 1);
array_needsize (signals, signalmax, w->signum, signals_init);
wlist_add ((struct ev_watcher_list **)&signals [w->signum - 1], (struct ev_watcher_list *)w);
wlist_add ((struct ev_watcher_list **)&signals [w->signum - 1].head, (struct ev_watcher_list *)w);
if (!w->next)
{
struct sigaction sa;
sa.sa_handler = sighandler;
sigfillset (&sa.sa_mask);
sa.sa_flags = 0;
sigaction (w->signum, &sa, 0);
}
}
void
@ -547,8 +631,11 @@ evsignal_stop (struct ev_signal *w)
if (!ev_is_active (w))
return;
wlist_del ((struct ev_watcher_list **)&signals [w->signum - 1], (struct ev_watcher_list *)w);
wlist_del ((struct ev_watcher_list **)&signals [w->signum - 1].head, (struct ev_watcher_list *)w);
ev_stop ((struct ev_watcher *)w);
if (!signals [w->signum - 1].head)
signal (w->signum, SIG_DFL);
}
/*****************************************************************************/
@ -568,6 +655,12 @@ ocb (struct ev_timer *w, int revents)
evtimer_start (w);
}
static void
scb (struct ev_signal *w, int revents)
{
fprintf (stderr, "signal %x,%d\n", revents, w->signum);
}
int main (void)
{
struct ev_io sin;
@ -580,7 +673,7 @@ int main (void)
struct ev_timer t[10000];
#if 1
#if 0
int i;
for (i = 0; i < 10000; ++i)
{
@ -598,6 +691,11 @@ int main (void)
evtimer_set_abs (&t1, 5, 10);
evtimer_start (&t1);
struct ev_signal sig;
evw_init (&sig, scb, 65535);
evsignal_set (&sig, SIGQUIT);
evsignal_start (&sig);
ev_loop (0);
return 0;

View File

@ -23,6 +23,7 @@ void epoll_postfork_child (void)
int fd;
epoll_fd = epoll_create (256);
fcntl (epoll_fd, F_SETFD, FD_CLOEXEC);
/* re-register interest in fds */
for (fd = 0; fd < anfdmax; ++fd)
@ -57,20 +58,20 @@ static void epoll_poll (ev_tstamp timeout)
}
}
int epoll_init (int flags)
void epoll_init (int flags)
{
epoll_fd = epoll_create (256);
if (epoll_fd < 0)
return 0;
return;
ev_method = EVMETHOD_EPOLL;
fcntl (epoll_fd, F_SETFD, FD_CLOEXEC);
ev_method = EVMETHOD_EPOLL;
method_fudge = 1e-3; /* needed to compensate for epoll returning early */
method_modify = epoll_modify;
method_poll = epoll_poll;
eventmax = 64; /* intiial number of events receivable per poll */
events = malloc (sizeof (struct epoll_event) * eventmax);
return 1;
}

View File

@ -79,14 +79,12 @@ static void select_poll (ev_tstamp timeout)
}
}
int select_init (int flags)
void select_init (int flags)
{
ev_method = EVMETHOD_SELECT;
ev_method = EVMETHOD_SELECT;
method_fudge = 1e-2; /* needed to compensate for select returning early, very conservative */
method_modify = select_modify;
method_poll = select_poll;
return 1;
}