diff options
| author | root <root> | 2007-11-06 18:49:32 +0000 | 
|---|---|---|
| committer | root <root> | 2007-11-06 18:49:32 +0000 | 
| commit | 0b7b062fb0b1c4f1ab22a52bd91f3c86195a084e (patch) | |
| tree | f3b759463d9b47888a9c98095a3748513f360e39 | |
| parent | 0268b6db718e75046444d22af082aedd7c4cae01 (diff) | |
*** empty log message ***rel-0_51
| -rw-r--r-- | ev.h | 3 | ||||
| -rw-r--r-- | ev_kqueue.c | 68 | ||||
| -rw-r--r-- | evdns.c | 2 | ||||
| -rw-r--r-- | event.c | 11 | 
4 files changed, 55 insertions, 29 deletions
| @@ -158,9 +158,6 @@ struct ev_io  struct ev_signal  {    EV_WATCHER_LIST (ev_signal); -#if EV_MULTIPLICITY -  struct ev_loop *loop; -#endif    int signum; /* ro */  }; diff --git a/ev_kqueue.c b/ev_kqueue.c index de566ff..4933270 100644 --- a/ev_kqueue.c +++ b/ev_kqueue.c @@ -56,21 +56,20 @@ kqueue_change (EV_P_ int fd, int filter, int flags, int fflags)  static void  kqueue_modify (EV_P_ int fd, int oev, int nev)  { -  if ((oev ^ nev) & EV_READ) -    { -      if (nev & EV_READ) -        kqueue_change (EV_A_ fd, EVFILT_READ, EV_ADD, NOTE_EOF); -      else -        kqueue_change (EV_A_ fd, EVFILT_READ, EV_DELETE, 0); -    } +  /* to detect close/reopen reliably, we have to remove and re-add */ +  /* event requests even when oev == nev */ -  if ((oev ^ nev) & EV_WRITE) -    { -      if (nev & EV_WRITE) -        kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_ADD, NOTE_EOF); -      else -        kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_DELETE, 0); -    } +  if (oev & EV_READ) +    kqueue_change (EV_A_ fd, EVFILT_READ, EV_DELETE, 0); + +  if (oev & EV_WRITE) +    kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_DELETE, 0); + +  if (nev & EV_READ) +    kqueue_change (EV_A_ fd, EVFILT_READ, EV_ADD, NOTE_EOF); + +  if (nev & EV_WRITE) +    kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_ADD, NOTE_EOF);  }  static void @@ -79,6 +78,14 @@ kqueue_poll (EV_P_ ev_tstamp timeout)    int res, i;    struct timespec ts; +  /* need to resize so there is enough space for errors */ +  if (kqueue_changecnt > kqueue_eventmax) +    { +      ev_free (kqueue_events); +      kqueue_eventmax = array_roundsize (struct kevent, kqueue_changecnt); +      kqueue_events = ev_malloc (sizeof (struct kevent) * kqueue_eventmax); +    } +    ts.tv_sec  = (time_t)timeout;    ts.tv_nsec = (long)(timeout - (ev_tstamp)ts.tv_sec) * 1e9;    res = kevent (kqueue_fd, kqueue_changes, kqueue_changecnt, kqueue_events, kqueue_eventmax, &ts); @@ -94,27 +101,42 @@ kqueue_poll (EV_P_ ev_tstamp timeout)    for (i = 0; i < res; ++i)      { +      int fd = kqueue_events [i].ident; +        if (kqueue_events [i].flags & EV_ERROR)          { +	  int err = kqueue_events [i].data; +            /*  -           * Error messages that can happen, when a delete fails. +           * errors that may happen             *   EBADF happens when the file discriptor has been             *   closed, -           *   ENOENT when the file discriptor was closed and +           *   ENOENT when the file descriptor was closed and             *   then reopened.             *   EINVAL for some reasons not understood; EINVAL             *   should not be returned ever; but FreeBSD does :-\ -           * An error is also indicated when a callback deletes -           * an event we are still processing.  In that case -           * the data field is set to ENOENT.             */ -          if (kqueue_events [i].data == EBADF) -            fd_kill (EV_A_ kqueue_events [i].ident); + +          /* we are only interested in errors for fds that we are interested in :) */ +          if (anfds [fd].events) +	    { +              if (err == ENOENT) /* resubmit changes on ENOENT */ +                kqueue_modify (EV_A_ fd, 0, anfds [fd].events); +              else if (err == EBADF) /* on EBADF, we re-check the fd */ +                { +                  if (fd_valid (fd)) +                    kqueue_modify (EV_A_ fd, 0, anfds [fd].events); +                  else +                    fd_kill (EV_A_ fd); +                } +              else /* on all other errors, we error out on the fd */ +                fd_kill (EV_A_ fd); +	    }          }        else          fd_event (            EV_A_ -          kqueue_events [i].ident, +          fd,            kqueue_events [i].filter == EVFILT_READ ? EV_READ            : kqueue_events [i].filter == EVFILT_WRITE ? EV_WRITE            : 0 @@ -124,7 +146,7 @@ kqueue_poll (EV_P_ ev_tstamp timeout)    if (expect_false (res == kqueue_eventmax))      {        ev_free (kqueue_events); -      kqueue_eventmax = array_roundsize (kqueue_events, kqueue_eventmax << 1); +      kqueue_eventmax = array_roundsize (struct kevent, kqueue_eventmax << 1);        kqueue_events = ev_malloc (sizeof (struct kevent) * kqueue_eventmax);      }  } @@ -1,4 +1,4 @@ -/* $Id: evdns.c,v 1.18 2007-11-06 17:20:42 root Exp $ */ +/* $Id: evdns.c,v 1.19 2007-11-06 18:49:32 root Exp $ */  /* The original version of this module was written by Adam Langley; for   * a history of modifications, check out the subversion logs. @@ -144,7 +144,12 @@ x_cb (struct event *ev, int revents)  static void  x_cb_sig (EV_P_ struct ev_signal *w, int revents)  { -  x_cb ((struct event *)(((char *)w) - offsetof (struct event, iosig.sig)), revents); +  struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.sig)); + +  if (revents & EV_ERROR) +    event_del (ev); + +  x_cb (ev, revents);  }  static void @@ -152,7 +157,9 @@ x_cb_io (EV_P_ struct ev_io *w, int revents)  {    struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.io)); -  if (!(ev->ev_events & EV_PERSIST) && ev_is_active (w)) +  if (revents & EV_ERROR) +    event_del (ev); +  else if (!(ev->ev_events & EV_PERSIST) && ev_is_active (w))      ev_io_stop (EV_A_ w);    x_cb (ev, revents); | 
