]> granicus.if.org Git - libevent/commitdiff
r16487@catbus: nickm | 2007-11-06 22:38:44 -0500
authorNick Mathewson <nickm@torproject.org>
Wed, 7 Nov 2007 03:40:26 +0000 (03:40 +0000)
committerNick Mathewson <nickm@torproject.org>
Wed, 7 Nov 2007 03:40:26 +0000 (03:40 +0000)
 Remove rtsig method, as discussed in July.  It hasn't compiled for quite a while, and nobody has seemed to miss it much.  Please let us know if this was a bad call. [Tracker issue 1826539].

svn:r485

ChangeLog
Makefile.am
configure.in
event.c
rtsig.c [deleted file]
test/test.sh

index 42b171914f01224cf742a578baf14758fb47e7c9..482d36f1f6f21f6493dc549efe0fdcc275e6e123 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -36,4 +36,5 @@ Changes in current version:
  o Begin using libtool's library versioning support correctly.  If we don't mess up, this will more or less guarantee binaries linked against old versions of libevent continue working when we make changes to libevent that do not break backward compatibility.
  o Fix evhttp.h compilation when TAILQ_ENTRY is not defined.
  o Small code cleanups in epoll_dispatch().
- o Increase the maximum number of addresses read from a packet in evdns to 32.
\ No newline at end of file
+ o Increase the maximum number of addresses read from a packet in evdns to 32.
+ o Remove support for the rtsig method: it hasn't compiled for a while, and nobody seems to miss it very much.  Let us know if there's a good reason to put it back in.
\ No newline at end of file
index 5f0836f388d9fcab60e8254c12cb9f1fa78b08be..35e019747480662fd9fe2a753072c16cf6bc27b2 100644 (file)
@@ -31,7 +31,7 @@ bin_SCRIPTS = event_rpcgen.py
 EXTRA_DIST = acconfig.h event.h event-internal.h log.h evsignal.h evdns.3 \
        evrpc.h evrpc-internal.h min_heap.h \
        event.3 \
-       kqueue.c epoll_sub.c epoll.c select.c rtsig.c poll.c signal.c \
+       kqueue.c epoll_sub.c epoll.c select.c poll.c signal.c \
        evport.c devpoll.c event_rpcgen.py \
        sample/Makefile.am sample/Makefile.in sample/event-test.c \
        sample/signal-test.c sample/time-test.c \
index 2bfc1771b3a476c73ab0ad1b7275da307fce2708..0cbf02967e145f25581fe5297eb41ff6d4690d95 100644 (file)
@@ -29,11 +29,6 @@ dnl   the command line with --enable-shared and --disable-shared.
 dnl AC_DISABLE_SHARED
 AC_SUBST(LIBTOOL_DEPS)
 
-dnl Check for optional stuff
-AC_ARG_WITH(rtsig,
-  [  --with-rtsig              compile with support for real time signals (experimental)],
-  [usertsig=yes], [usertsig=no])
-
 dnl Checks for libraries.
 AC_CHECK_LIB(socket, socket)
 AC_CHECK_LIB(resolv, inet_aton)
@@ -164,58 +159,10 @@ if test "x$haveselect" = "xyes" ; then
 fi
 
 havepoll=no
-havertsig=no
 AC_CHECK_FUNCS(poll, [havepoll=yes], )
 if test "x$havepoll" = "xyes" ; then
        AC_LIBOBJ(poll)
        needsignal=yes
-
-       if test "x$usertsig" = "xyes" ; then
-               AC_CHECK_FUNCS(sigtimedwait, [havertsig=yes], )
-       fi
-fi
-if test "x$havertsig" = "xyes" ; then
-       AC_MSG_CHECKING(for F_SETSIG in fcntl.h)
-       AC_EGREP_CPP(yes,
-[
-#define _GNU_SOURCE
-#include <fcntl.h>
-#ifdef F_SETSIG
-yes
-#endif
-],     [ AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no); havertsig=no])
-fi
-if test "x$havertsig" = "xyes" ; then
-       AC_DEFINE(HAVE_RTSIG, 1, [Define if your system supports POSIX realtime signals])
-       AC_LIBOBJ(rtsig)
-       AC_MSG_CHECKING(for working rtsig on pipes)
-       AC_TRY_RUN(
-[
-#define _GNU_SOURCE
-#include <fcntl.h>
-#include <signal.h>
-#include <unistd.h>
-
-int sigio()
-{
-       exit(0);
-}
-
-int main()
-{
-       int fd[2];
-
-       pipe(fd);
-       signal(SIGIO, sigio);
-       fcntl(fd[0], F_SETOWN, getpid());
-       fcntl(fd[0], F_SETSIG, SIGIO);
-       fcntl(fd[0], F_SETFL, fcntl(fd[0], F_GETFL) | O_ASYNC);
-       write(fd[1], "", 1);
-       return 1;
-}
-],     [ AC_MSG_RESULT(yes)
-         AC_DEFINE(HAVE_WORKING_RTSIG, 1, [Define if realtime signals work on pipes])],
-       AC_MSG_RESULT(no))
 fi
 
 haveepoll=no
diff --git a/event.c b/event.c
index 99f585644193423fb90238010e8af437f4d3ffad..391d317ff970aa59a0eea88bce4d1b4f14f2f10c 100644 (file)
--- a/event.c
+++ b/event.c
@@ -65,9 +65,6 @@ extern const struct eventop selectops;
 #ifdef HAVE_POLL
 extern const struct eventop pollops;
 #endif
-#ifdef HAVE_RTSIG
-extern const struct eventop rtsigops;
-#endif
 #ifdef HAVE_EPOLL
 extern const struct eventop epollops;
 #endif
@@ -95,9 +92,6 @@ const struct eventop *eventops[] = {
 #ifdef HAVE_DEVPOLL
        &devpollops,
 #endif
-#ifdef HAVE_RTSIG
-       &rtsigops,
-#endif
 #ifdef HAVE_POLL
        &pollops,
 #endif
diff --git a/rtsig.c b/rtsig.c
deleted file mode 100644 (file)
index 66ed184..0000000
--- a/rtsig.c
+++ /dev/null
@@ -1,996 +0,0 @@
-/*
- * Copyright (c) 2006 Mathew Mills <mathewmills@mac.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/*
- * Meta-level comments: You know that a kernel interface is wrong if
- * supporting it requires three times more code than any of the other
- * kernel interfaces supported in libevent.  Niels - 2006-02-22
- */
-/**
-
-   "RTSIG" is a shorthand for using O_ASYNC to make descriptors send
-   signals when readable/writable and to use POSIX real-time signals
-   witch are queued unlike normal signals.  At first blush this may
-   seem like a alternative to epoll, but a number of problems arise
-   when attempting to build an eventloop entirely out of rtsig.
-   Still, we can use rtsig in combination with poll() to
-   provide an eventloop that allows for many thousands of sockets
-   without huge overheads implicit with using select() or poll()
-   alone.  epoll and kqueue are far superior to rtsig and should be
-   used where available, but rtsig has been in standard Linux kernels
-   for a long time and have a huge installation base.  epoll requires
-   special patches for 2.4 kernels and 2.6 kernels are not yet nearly
-   so ubiquitous.
-
-   rtsig problems:
-    - O_ASYNC mechanisms work only on sockets - not pipes or tty's
-
-    - O_ASYNC signals are edge-triggered, POLLIN on packet arriving
-   or socket close; POLLOUT when a socket transitions from
-   non-writable to writable.  Being edge-triggered means the
-   event-handler callbacks must transition the level ( reading
-   completely the socket buffer contents ) or it will be unable to
-   reliably receive notification again.
-
-   - rtsig implementations must be intimately involved in how a
-   process dispatches signals.
-
-   - delivering signals per-event can be expensive, CPU-wise, but
-     sigtimedwait() blocks on signals only and means non-sockets
-     cannot be serviced.
-
-   Theory of operation:
-    This libevent module uses rtsig to allow us to manage a set of
-    poll-event descriptors.  We can drop uninteresting fd's from the
-    pollset if the fd will send a signal when it becomes interesting
-    again.
-
-    poll() offers us level-triggering and, when we have verified the
-    level of a socket, we can trust the edge-trigger nature of the
-    ASYNC signal.
-
-    As an eventloop we must poll for external events but leverage
-    kernel functionality to sleep between events ( until the loop's
-    next scheduled timed event ).
-
-    If we are polling on any non-sockets then we simply have no choice
-    about blocking on the poll() call.  If we blocked on the
-    sigtimedwait() call as rtsig papers recommend we will not wake on
-    non-socket state transitions.  As part of libevent, this module
-    must support non-socket polling.
-
-    Many applications, however, do not need to poll on non-sockets and
-    so this module should be able to optimize this case by using
-    sigtimedwait().  For this reason this module can actually trigger
-    events in each of three different ways:
-      - poll() returning ready events from descriptors in the pollset
-
-      - real-time signals dequeued via sigtimedwait()
-
-      - real-time signals that call an installed signal handler which in
-    turn writes the contents of siginfo to one end of a socketpair
-    DGRAM socket.  The other end of the socket is always in the
-    pollset so poll will be guaranteed to return even if the signal is
-    received before entering poll().
-
-    non-socket descriptors force us to block on the poll() for the
-    duration of a dispatch.  In this case we unblock (w/ sigprocmask)
-    the managed signals just before polling.  Each managed signal is
-    handled by signal_handler() which send()'s the contents of siginfo
-    over the socketpair.  Otherwise, we call poll() with a timeout of
-    0ms so it checks the levels of the fd's in the pollset and returns
-    immediately.  Any fd that is a socket and has no active state is
-    removed from the pollset for the next pass -- we will rely on
-    getting a signal for events on these fd's.
-
-    The receiving end of the siginfo socketpair is in the pollset
-    (permanently) so if we are polling on non-sockets, the delivery of
-    signals immediately following sigprocmask( SIG_UNBLOCK...) will
-    result in a readable op->signal_recv_fd which ensures the poll()
-    will return immediately.  If the poll() call is blocking and a
-    signal arrives ( possibly a real-time signal from a socket not in
-    the pollset ) its handler will write the data to the socketpair
-    and interrupt the poll().
-
-    After every poll call we attempt a non-blocking recv from the
-    signal_recv_fd and continue to recv and dispatch the events until
-    recv indicates the socket buffer is empty.
-
-    One might raise concerns about receiving event activations from
-    both poll() and from the rtsig data in the signal_recv_fd.
-    Fortunately, libevent is already structured for event coalescing,
-    so this issue is mitigated ( though we do some work twice for the
-    same event making us less efficient ).  I suspect that the cost of
-    turning off the O_ASYNC flag on fd's in the pollset is more
-    expensive than handling some events twice.  Looking at the
-    kernel's source code for setting O_ASYNC, it looks like it takes a
-    global kernel lock...
-
-    After a poll and recv-loop for the signal_recv_fd, we finally do a
-    sigtimedwait().  sigtimedwait will only block if we haven't
-    blocked in poll() and we have not enqueued events from either the
-    poll or the recv-loop.  Because sigtimedwait blocks all signals
-    that are not in the set of signals to be dequeued, we need to
-    dequeue almost all signals and make sure we dispatch them
-    correctly.  We dequeue any signal that is not blocked as well as
-    all libevent-managed signals.  If we get a signal that is not
-    managed by libevent we lookup the sigaction for the specific
-    signal and call that function ourselves.
-
-    Finally, I should mention that getting a SIGIO signal indicates
-    that the rtsig buffer has overflowed and we have lost events.
-    This forces us to add _every_ descriptor to the pollset to recover.
-
-*/
-
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* Enable F_SETSIG and F_SETOWN */
-#define _GNU_SOURCE
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <sys/_time.h>
-#endif
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/poll.h>
-#include <sys/queue.h>
-#include <unistd.h>
-#include <sys/socket.h>
-
-#include "event.h"
-#include "event-internal.h"
-#include "log.h"
-extern struct event_list signalqueue;
-
-#include <linux/unistd.h>
-#ifndef __NR_gettid
-#define gettid() getpid()
-#else
-
-#if ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 3)))
-_syscall0(pid_t,gettid)
-#endif
-
-#endif
-
-#define EVLIST_NONSOCK   0x1000 /* event is for a non-socket file-descriptor */
-#define EVLIST_DONTDEL   0x2000 /* event should always be in the pollset */
-#define MAXBUFFERSIZE (1024 * 1024 * 2) /* max socketbuffer for signal-spair */
-#define INIT_MAX 16     /* init/min # of fd positions in our pollset */
-
-static int signal_send_fd[_NSIG]; /* the globalend of the signal socketpair */
-static int trouble[_NSIG]; /* 1 when signal-handler cant send to signal_send_fd */
-
-struct rtdata;
-TAILQ_HEAD(rtdata_list, rtdata);
-
-struct rtsigop {
-       sigset_t sigs;        /* signal mask for all _managed_ signals */
-       struct pollfd *poll;  /* poll structures */
-       struct rtdata **ptodat;  /* map poll_position to rtdata */
-       int cur;              /* cur # fd's in a poll set */
-       int max;              /* max # fd's in a poll set, start at 16 and grow as needed */
-       int total;            /* count of fd's we are watching now */
-       int signo;            /* the signo we use for ASYNC fd notifications */
-       int nonsock;          /* number of non-socket fd's we are watching */
-       int highestfd;        /* highest fd accomodated by fdtodat */
-       struct rtdata_list **fdtodat; /* map fd to rtdata ( and thus to event ) */
-       int signal_recv_fd;   /* recv side of the signal_send_fd */
-       int signal_send_fd;   /* recv side of the signal_send_fd */
-       struct event sigfdev; /* our own event structure for the signal fd */
-};
-
-struct rtdata {
-       /* rtdata holds rtsig-private state on each event */
-       TAILQ_ENTRY (rtdata) next;
-       struct event *ev;
-       int poll_position;
-};
-
-void *rtsig_init(struct event_base *);
-int rtsig_add(void *, struct event *);
-int rtsig_del(void *, struct event *);
-int rtsig_recalc(struct event_base *, void *, int);
-int rtsig_dispatch(struct event_base *, void *, struct timeval *);
-
-struct eventop rtsigops = {
-       "rtsig",
-       rtsig_init,
-       rtsig_add,
-       rtsig_del,
-       rtsig_recalc,
-       rtsig_dispatch
-};
-
-static void
-signal_handler(int sig, siginfo_t *info, void *ctx)
-{
-       /*
-        * the signal handler for all libevent-managed signals only
-        * used if we need to do a blocking poll() call due to
-        * non-socket fd's in the pollset.
-        */
-  
-       siginfo_t *i = info;
-       siginfo_t i_local;
-
-       if (trouble[sig - 1]) {
-               i_local.si_signo = SIGIO;
-               i_local.si_errno = 0;
-               i_local.si_code = 0;
-               i = &i_local;
-               trouble[sig - 1] = 0;
-       }
-
-       if (send(signal_send_fd[sig - 1], i, sizeof(*i),
-               MSG_DONTWAIT|MSG_NOSIGNAL) == -1)
-               trouble[sig - 1] = 1;
-}
-
-static void
-donothing(int fd, short event, void *arg)
-{
-       /*
-        * callback for our signal_recv_fd event structure
-        * we don't want to act on these events, we just want to wake the poll()
-        */
-};
-
-static void
-signotset(sigset_t *set)
-{
-       int i, l;
-       l = sizeof(*set) / 4;
-       for (i = 0; i < l; i++) {
-               ((unsigned *)set)[i] = ~((unsigned *)set)[i];
-       }
-}
-
-/*  The next three functions manage our private data about each event struct */
-
-static int
-grow_fdset(struct rtsigop *op, int newhigh)
-{
-       /*
-        * grow the fd -> rtdata array because we have encountered a
-        * new fd too high to fit in the existing array
-        */
-
-       struct rtdata_list **p;
-       struct rtdata_list *datset;
-       int i,x;
-       int newcnt = (newhigh + 1) << 1;
-
-       if (newhigh <= op->highestfd)
-               return (0);
-
-       p = op->fdtodat;
-       p = realloc(op->fdtodat, sizeof(struct rtdata_list *) * newcnt);
-       if (p == NULL)
-               return (-1);
-       op->fdtodat = p;
-
-       datset = calloc(newcnt - (op->highestfd + 1),
-           sizeof(struct rtdata_list));
-       if (datset == NULL)
-               return (-1);
-
-       for (i = op->highestfd + 1, x = 0; i < newcnt; i++, x++) {
-               op->fdtodat[i] = &(datset[x]);
-               TAILQ_INIT(op->fdtodat[i]);
-       }
-
-       op->highestfd = newcnt - 1;
-       return (0);
-}
-
-static struct rtdata *
-ev2dat(struct rtsigop *op, struct event *ev, int create)
-{
-       /*
-        * given an event struct, find the dat structure that
-        * corresponds to it if create is non-zero and the rtdata
-        * structure does not exist, create it return NULL if not
-        * found
-        */
-
-       int found = 0;
-       int fd = ev->ev_fd;
-       struct rtdata *ret = NULL;
-
-       if (op->highestfd < fd && create)
-               if (grow_fdset(op, fd) == -1)
-                       return (NULL);
-  
-       TAILQ_FOREACH(ret, op->fdtodat[fd], next) {
-               if (ret->ev == ev) {
-                       found = 1;
-                       break;
-               }
-       }
-
-       if (!found) {
-               if (!create)
-                       return (NULL);
-
-               ret = calloc(1, sizeof(struct rtdata));
-               if (ret == NULL)
-                       return (NULL);
-               ret->ev = ev;
-               ret->poll_position = -1;
-               TAILQ_INSERT_TAIL(op->fdtodat[fd], ret, next);
-       }
-
-       return (ret);
-}
-
-static void
-dat_del(struct rtsigop *op, struct rtdata *dat)
-{
-       /*
-        * delete our private notes about a given event struct
-        * called from rtsig_del() only
-        */
-       int fd;
-       if (dat == NULL)
-               return;
-       fd = dat->ev->ev_fd;
-
-       TAILQ_REMOVE(op->fdtodat[fd], dat, next);
-       memset(dat, 0, sizeof(*dat));
-       free(dat);
-}
-
-
-static void
-set_sigaction(int sig)
-{
-       /*
-        * set the standard handler for any libevent-managed signal,
-        * including the rtsig used for O_ASYNC notifications
-        */
-       struct sigaction act;
-
-       act.sa_flags = SA_RESTART | SA_SIGINFO;
-       sigfillset(&(act.sa_mask));
-       act.sa_sigaction = &signal_handler;
-       sigaction(sig, &act, NULL);
-}
-
-static int
-find_rt_signal()
-{
-       /* find an unused rtsignal */
-       struct sigaction act;
-       int sig = SIGRTMIN;
-
-       while (sig <= SIGRTMAX) {
-               if (sigaction(sig, NULL, &act) != 0) {
-                       if (errno == EINTR)
-                               continue;
-               } else {
-                       if (act.sa_flags & SA_SIGINFO) {
-                               if (act.sa_sigaction == NULL)
-                                       return (sig);
-                       } else {
-                               if (act.sa_handler == SIG_DFL)
-                                       return (sig);
-                       }
-               }
-               sig++;
-       }
-       return (0);
-}
-
-/*
- * the next three functions manage our pollset and the memory management for 
- * fd -> rtdata -> event -> poll_position maps
- */
-
-static int
-poll_add(struct rtsigop *op, struct event *ev, struct rtdata *dat)
-{
-       struct pollfd *pfd;
-       int newmax = op->max << 1;
-       int pp;
-
-       if (op->poll == NULL)
-               return (0);
-
-       if (dat == NULL)
-               dat = ev2dat(op, ev, 0);
-
-       if (dat == NULL)
-               return (0);
-
-       pp = dat->poll_position;
-
-       if (pp != -1) {
-               pfd = &op->poll[pp];
-               if (ev->ev_events & EV_READ)
-                       pfd->events |= POLLIN;
-    
-               if (ev->ev_events & EV_WRITE)
-                       pfd->events |= POLLOUT;
-    
-               return (0);
-       }
-
-       if (op->cur == op->max) {
-               void *p = realloc(op->poll, sizeof(*op->poll) * newmax);
-               if (p == NULL) {
-                       errno = ENOMEM;
-                       return (-1);
-               }
-               op->poll = p;
-
-               p = realloc(op->ptodat, sizeof(*op->ptodat) * newmax);
-               if (p == NULL) {
-                       /* shrink the pollset back down */
-                       op->poll = realloc(op->poll,
-                           sizeof(*op->poll) * op->max);
-                       errno = ENOMEM;
-                       return (-1);
-               }
-               op->ptodat = p;
-               op->max = newmax;
-       }
-
-       pfd = &op->poll[op->cur];
-       pfd->fd = ev->ev_fd;
-       pfd->revents = 0;
-       pfd->events = 0;
-
-       if (ev->ev_events & EV_READ)
-               pfd->events |= POLLIN;
-  
-       if (ev->ev_events & EV_WRITE)
-               pfd->events |= POLLOUT;
-  
-       op->ptodat[op->cur] = dat;
-       dat->poll_position = op->cur;
-       op->cur++;
-
-       return (0);
-}
-
-static void
-poll_free(struct rtsigop *op, int n)
-{
-  if (op->poll == NULL)
-         return;
-
-  op->cur--;
-
-  if (n < op->cur) {
-    memcpy(&op->poll[n], &op->poll[op->cur], sizeof(*op->poll));
-    op->ptodat[n] = op->ptodat[op->cur];
-    op->ptodat[n]->poll_position = n;
-  }
-
-
-  /* less then half the max in use causes us to shrink */
-  if (op->max > INIT_MAX && op->cur < op->max >> 1) {
-    op->max >>= 1;
-    op->poll = realloc(op->poll, sizeof(*op->poll) * op->max);
-    op->ptodat = realloc(op->ptodat, sizeof(*op->ptodat) * op->max);
-  }
-}
-
-static void
-poll_remove(struct rtsigop *op, struct event *ev, struct rtdata *dat)
-{
-  int pp;
-  if (dat == NULL)
-    dat = ev2dat(op, ev, 0);
-
-  if (dat == NULL) return;
-
-  pp = dat->poll_position;
-  if (pp != -1) {
-    poll_free(op, pp);
-    dat->poll_position = -1;
-  }
-}
-
-static void
-activate(struct event *ev, int flags)
-{
-       /* activate an event, possibly removing one-shot events */
-       if (!(ev->ev_events & EV_PERSIST))
-               event_del(ev);
-       event_active(ev, flags, 1);
-}
-
-#define FD_CLOSEONEXEC(x) do { \
-        if (fcntl(x, F_SETFD, 1) == -1) \
-                event_warn("fcntl(%d, F_SETFD)", x); \
-} while (0)
-
-void *
-rtsig_init(struct event_base *)
-{
-       struct rtsigop *op;
-       int sockets[2];
-       int optarg;
-       struct rtdata *dat;
-       int flags;
-
-       if (getenv("EVENT_NORTSIG"))
-               goto err;
-
-       op = calloc(1, sizeof(*op));
-       if (op == NULL)
-               goto err;
-
-       op->max = INIT_MAX;
-       op->poll = malloc(sizeof(*op->poll) * op->max);
-       if (op->poll == NULL) 
-               goto err_free_op;
-
-       op->signo = find_rt_signal();
-       if (op->signo == 0)
-               goto err_free_poll;
-  
-       op->nonsock = 0;
-
-       if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sockets) != 0)
-               goto err_free_poll;
-
-       FD_CLOSEONEXEC(sockets[0]);
-       FD_CLOSEONEXEC(sockets[1]);
-
-       signal_send_fd[op->signo - 1] = sockets[0];
-       trouble[op->signo - 1] = 0;
-       op->signal_send_fd = sockets[0];
-       op->signal_recv_fd = sockets[1];
-       flags = fcntl(op->signal_recv_fd, F_GETFL);
-       fcntl(op->signal_recv_fd, F_SETFL, flags | O_NONBLOCK);
-
-       optarg = MAXBUFFERSIZE;
-       setsockopt(signal_send_fd[op->signo - 1],
-           SOL_SOCKET, SO_SNDBUF, 
-           &optarg, sizeof(optarg));
-  
-       optarg = MAXBUFFERSIZE;
-       setsockopt(op->signal_recv_fd,
-           SOL_SOCKET, SO_RCVBUF,
-           &optarg, sizeof(optarg));
-
-       op->highestfd = -1;
-       op->fdtodat = NULL;
-       if (grow_fdset(op, 1) == -1)
-               goto err_close_pair;
-
-       op->ptodat = malloc(sizeof(*op->ptodat) * op->max);
-       if (op->ptodat == NULL)
-               goto err_close_pair;
-
-       sigemptyset(&op->sigs);
-       sigaddset(&op->sigs, SIGIO);
-       sigaddset(&op->sigs, op->signo);
-       sigprocmask(SIG_BLOCK, &op->sigs, NULL);
-       set_sigaction(SIGIO);
-       set_sigaction(op->signo);
-
-       event_set(&(op->sigfdev), op->signal_recv_fd, EV_READ|EV_PERSIST,
-           donothing, NULL);
-       op->sigfdev.ev_flags |= EVLIST_DONTDEL;
-       dat = ev2dat(op, &(op->sigfdev), 1);
-       poll_add(op, &(op->sigfdev), dat);
-
-       return (op);
-
- err_close_pair:
-       close(op->signal_recv_fd);
-       close(signal_send_fd[op->signo - 1]);
-
- err_free_poll:
-       free(op->poll);
- err_free_op:
-       free(op);
- err:
-       return (NULL);
-}
-
-int
-rtsig_add(void *arg, struct event *ev)
-{
-       struct rtsigop *op = (struct rtsigop *) arg;
-       int flags, i;
-       struct stat statbuf;
-       struct rtdata *dat;
-
-       if (ev->ev_events & EV_SIGNAL) {
-               int signo = EVENT_SIGNAL(ev);
-  
-               sigaddset(&op->sigs, EVENT_SIGNAL(ev));
-               if (sigprocmask(SIG_BLOCK, &op->sigs, NULL) == -1)
-                       return (-1);
-    
-               set_sigaction(signo);
-    
-               signal_send_fd[signo - 1] = op->signal_send_fd;
-               trouble[signo - 1] = 0;
-
-               return (0);
-       }
-
-       if (!(ev->ev_events & (EV_READ|EV_WRITE))) 
-               return (0);
-
-       if (-1 == fstat(ev->ev_fd, &statbuf))
-               return (-1);
-
-       if (!S_ISSOCK(statbuf.st_mode))
-               ev->ev_flags |= EVLIST_NONSOCK;
-
-       flags = fcntl(ev->ev_fd, F_GETFL);
-       if (flags == -1)
-               return (-1);
-
-       if (!(flags & O_ASYNC)) {
-               if (fcntl(ev->ev_fd, F_SETSIG, op->signo) == -1 ||
-                   fcntl(ev->ev_fd, F_SETOWN, (int) gettid()) == -1)
-                       return (-1);
-    
-               /*
-                * the overhead of always handling writeable edges
-                * isn't going to be that bad...
-                */
-               if (fcntl(ev->ev_fd, F_SETFL, flags | O_ASYNC|O_RDWR)) 
-                       return (-1);
-       }
-
-#ifdef O_ONESIGFD
-       /*
-        * F_SETAUXFL and O_ONESIGFD are defined in a non-standard
-        * linux kernel patch to coalesce events for fds
-        */
-       fcntl(ev->ev_fd, F_SETAUXFL, O_ONESIGFD);
-#endif
-
-       dat = ev2dat(op, ev, 1);
-       if (dat == NULL)
-               return (-1);
-
-       op->total++;
-       if (ev->ev_flags & EVLIST_NONSOCK)
-               op->nonsock++;
-
-       if (poll_add(op, ev, dat) == -1) {
-               /* must check the level of new fd's */
-               i = errno;
-               fcntl(ev->ev_fd, F_SETFL, flags);
-               errno = i;
-               return (-1);
-       }
-
-       return (0);
-}
-
-int
-rtsig_del(void *arg, struct event *ev)
-{
-       struct rtdata *dat;
-       struct rtsigop *op = (struct rtsigop *) arg;
-
-       if (ev->ev_events & EV_SIGNAL) {
-               sigset_t sigs;
-
-               sigdelset(&op->sigs, EVENT_SIGNAL(ev));
-    
-               sigemptyset(&sigs);
-               sigaddset(&sigs, EVENT_SIGNAL(ev));
-               return (sigprocmask(SIG_UNBLOCK, &sigs, NULL));
-       }
-
-       if (!(ev->ev_events & (EV_READ|EV_WRITE)))
-               return (0);
-
-       dat = ev2dat(op, ev, 0);
-       poll_remove(op, ev, dat);
-       dat_del(op, dat);
-       op->total--;
-       if (ev->ev_flags & EVLIST_NONSOCK)
-               op->nonsock--;
-
-       return (0);
-}
-
-int
-rtsig_recalc(struct event_base *base, void *arg, int max)
-{
-       return (0);
-}
-
-/*
- * the following do_X functions implement the different stages of a single
- * eventloop pass: poll(), recv(sigsock), sigtimedwait()
- *
- * do_siginfo_dispatch() is a common factor to both do_sigwait() and
- * do_signals_from_socket().
- */
-
-static inline int
-do_poll(struct rtsigop *op, struct timespec *ts, struct timespec **ts_p)
-{
-       int res = 0;
-       int i = 0;
-  
-       if (op->cur > 1) {
-               /* non-empty poll set (modulo the signalfd) */
-               if (op->nonsock) {
-                       int timeout = -1;
-                       
-                       if (*ts_p != NULL)
-                               timeout = (*ts_p)->tv_nsec / 1000000
-                                         + (*ts_p)->tv_sec * 1000;
-                       
-                       sigprocmask(SIG_UNBLOCK, &(op->sigs), NULL);
-
-                       res = poll(op->poll, op->cur, timeout);
-                       
-                       sigprocmask(SIG_BLOCK, &(op->sigs), NULL);
-                       
-                       ts->tv_sec = 0;
-                       ts->tv_nsec = 0;
-                       *ts_p = ts;
-               } else {
-                       res = poll(op->poll, op->cur, 0);
-               }
-
-               if (res < 0) {
-                       return (errno == EINTR ? 0 : -1);
-               } else if (res) {
-                       ts->tv_sec = 0;
-                       ts->tv_nsec = 0;
-                       *ts_p = ts;
-               }
-
-               i = 0;
-               while (i < op->cur) {
-                       struct rtdata *dat = op->ptodat[i];
-                       struct event *ev = dat->ev;
-
-                       if (op->poll[i].revents) {
-                               int flags = 0;
-       
-                               if (op->poll[i].revents & (POLLIN | POLLERR))
-                                       flags |= EV_READ;
-       
-                               if (op->poll[i].revents & POLLOUT)
-                                       flags |= EV_WRITE;
-       
-                               if (!(ev->ev_events & EV_PERSIST)) {
-                                       poll_remove(op, ev, op->ptodat[i]);
-                                       event_del(ev);
-                               } else {
-                                       i++;
-                               }
-       
-                               event_active(ev, flags, 1);
-                       } else {
-                               if (ev->ev_flags & (EVLIST_NONSOCK|EVLIST_DONTDEL)) {
-                                       i++;
-                               } else {
-                                       poll_remove(op, ev, op->ptodat[i]);
-                               }
-                       }
-               }
-       }
-       return (res);
-}
-
-static inline int
-do_siginfo_dispatch(struct event_base *base, struct rtsigop *op,
-    siginfo_t *info)
-{
-       int signum;
-       struct rtdata *dat, *next_dat;
-       struct event *ev, *next_ev;
-
-       if (info == NULL)
-               return (-1);
-
-       signum = info->si_signo;
-       if (signum == op->signo) {
-               int flags, sigok = 0;
-               flags = 0;
-
-               if (info->si_band & (POLLIN|POLLERR))
-                       flags |= EV_READ;
-               if (info->si_band & POLLOUT)
-                       flags |= EV_WRITE;
-
-               if (!flags)
-                       return (0);
-
-               if (info->si_fd > op->highestfd)
-                       return (-1);
-
-               dat = TAILQ_FIRST(op->fdtodat[info->si_fd]);
-               while (dat != TAILQ_END(op->fdtodat[info->si_fd])) {
-                       next_dat = TAILQ_NEXT(dat, next);
-                       if (flags & dat->ev->ev_events) {
-                               ev = dat->ev;
-                               poll_add(op, ev, dat);
-                               activate(ev, flags & ev->ev_events);
-                               sigok = 1;
-                       }
-                       dat = next_dat;
-               }
-       } else if (signum == SIGIO) {
-               TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
-                       if (ev->ev_events & (EV_READ|EV_WRITE))
-                               poll_add(op, ev, NULL);
-               }
-               return (1); /* 1 means the caller should poll() again */
-    
-       } else if (sigismember(&op->sigs, signum)) {
-               /* managed signals are queued */
-               ev = TAILQ_FIRST(&signalqueue);
-               while (ev != TAILQ_END(&signalqueue)) {
-                       next_ev = TAILQ_NEXT(ev, ev_signal_next);
-                       if (EVENT_SIGNAL(ev) == signum)
-                               activate(ev, EV_SIGNAL);
-                       ev = next_ev;
-               }
-       } else {
-               /* dispatch unmanaged signals immediately */
-               struct sigaction sa;
-               if (sigaction(signum, NULL, &sa) == 0) {
-                       if ((sa.sa_flags & SA_SIGINFO) && sa.sa_sigaction) {
-                               (*sa.sa_sigaction)(signum, info, NULL);
-                       } else if (sa.sa_handler) {
-                               if ((int)sa.sa_handler != 1)
-                                       (*sa.sa_handler)(signum);
-                       } else {
-                               if (signum != SIGCHLD) {
-                                       /* non-blocked SIG_DFL */
-                                       kill(gettid(), signum);
-                               }
-                       }
-               }
-       }
-
-       return (0);
-}
-
-/*
- * return 1 if we should poll again
- * return 0 if we are all set
- * return -1 on error
- */
-static inline int
-do_sigwait(struct event_base *base, struct rtsigop *op,
-    struct timespec *ts, struct timespec **ts_p, sigset_t *sigs)
-{
-       for (;;) {
-               siginfo_t info;
-               int signum;
-
-               signum = sigtimedwait(sigs, &info, *ts_p);
-
-               ts->tv_sec = 0;
-               ts->tv_nsec = 0;
-               *ts_p = ts;
-
-               if (signum == -1) {
-                       if (errno == EAGAIN || errno == EINTR)
-                               return (0);
-                       return (-1);
-               } else if (1 == do_siginfo_dispatch(base, op, &info)) {
-                       return (1);
-               }
-       }
-
-       /* NOTREACHED */
-}
-
-static inline int
-do_signals_from_socket(struct event_base *base, struct rtsigop *op,
-    struct timespec *ts, struct timespec **ts_p)
-{
-       int fd = op->signal_recv_fd;
-       siginfo_t info;
-       int res;
-
-       for (;;) {
-               res = recv(fd, &info, sizeof(info), MSG_NOSIGNAL);
-               if (res == -1) {
-                       if (errno == EAGAIN)
-                               return (0);
-                       if (errno == EINTR)
-                               continue;
-                       return (-1);
-               } else {
-                       ts->tv_sec = 0;
-                       ts->tv_nsec = 0;
-                       *ts_p = ts;
-                       if (1 == do_siginfo_dispatch(base, op, &info))
-                               return (1);
-               }
-       }
-       /* NOTREACHED */
-}
-
-int
-rtsig_dispatch(struct event_base *base, void *arg, struct timeval *tv)
-{
-       struct rtsigop *op = (struct rtsigop *) arg;
-       struct timespec ts, *ts_p = NULL;
-       int res;
-       sigset_t sigs;
-
-       if (tv != NULL) {
-               ts.tv_sec = tv->tv_sec;
-               ts.tv_nsec = tv->tv_usec * 1000;
-               *ts_p = ts;
-       }
-
- poll_for_level:
-       /* ts and ts_p can be modified in do_XXX() */
-       res = do_poll(op, &ts, &ts_p);
-
-       res = do_signals_from_socket(base, op, &ts, &ts_p);
-       if (res == 1)
-               goto poll_for_level;
-       else if (res == -1)
-               return (-1);
-
-       /*
-        * the mask = managed_signals | unblocked-signals
-        * MM - if this is not blocking do we need to cast the net this wide?
-        */
-       sigemptyset(&sigs);
-       sigprocmask(SIG_BLOCK, &sigs, &sigs);
-       signotset(&sigs);
-       sigorset(&sigs, &sigs, &op->sigs);
-
-       res = do_sigwait(base, op, &ts, &ts_p, &sigs);
-
-       if (res == 1)
-               goto poll_for_level;
-       else if (res == -1)
-               return (-1);
-
-       return (0);
-}
-
index e91a5a9af2f763faa11efdeb250b67d09112b4db..506a1988c34b6cd59d2ff7dee9043ca5a0a785a0 100755 (executable)
@@ -6,7 +6,6 @@ setup () {
         EVENT_NOPOLL=yes; export EVENT_NOPOLL
         EVENT_NOSELECT=yes; export EVENT_NOSELECT
         EVENT_NOEPOLL=yes; export EVENT_NOEPOLL
-        EVENT_NORTSIG=yes; export EVENT_NORTSIG
         EVENT_NOEVPORT=yes; export EVENT_NOEVPORT
 }
 
@@ -76,12 +75,6 @@ export EVENT_NOSELECT
 echo "SELECT"
 test
 
-setup
-unset EVENT_NORTSIG
-export EVENT_NORTSIG
-echo "RTSIG"
-test
-
 setup
 unset EVENT_NOEPOLL
 export EVENT_NOEPOLL