diff options
| author | root <root> | 2011-01-05 04:21:20 +0000 | 
|---|---|---|
| committer | root <root> | 2011-01-05 04:21:20 +0000 | 
| commit | 0dd9e41836e852b2f0e55598508482d3d2e82f2d (patch) | |
| tree | 64691fb20acba3c4cbd317c5a461a66ba2803296 | |
| parent | 470ac58f4377282a5bd893f63445266e1d2c3b7c (diff) | |
*** empty log message ***
| -rw-r--r-- | ev_epoll.c | 33 | 
1 files changed, 31 insertions, 2 deletions
@@ -1,7 +1,7 @@  /*   * libev epoll fd activity backend   * - * 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- @@ -53,7 +53,8 @@   *    (such as files). while not critical, no other advanced interface   *    seems to share this (rather non-unixy) limitation.   * e) epoll claims to be embeddable, but in practise you never get - *    a ready event for the epoll fd. + *    a ready event for the epoll fd (broken: <=2.6.26, working: >=2.6.32). + * f) epoll_ctl returning EPERM means the fd is always ready.   *   * lots of "weird code" and complication handling in this file is due   * to these design problems with epoll, as we try very hard to avoid @@ -64,6 +65,8 @@  #include <sys/epoll.h> +#define EV_EMASK_EPERM 0x80 +  static void  epoll_modify (EV_P_ int fd, int oev, int nev)  { @@ -112,6 +115,19 @@ epoll_modify (EV_P_ int fd, int oev, int nev)        if (!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev))          return;      } +  else if (expect_true (errno == EPERM)) +    { +      anfds [fd].emask = EV_EMASK_EPERM; + +      /* add fd to epoll_eperms, if not already inside */ +      if (!(oldmask & EV_EMASK_EPERM)) +        { +          array_needsize (int, epoll_eperms, epoll_epermmax, epoll_epermcnt + 1, EMPTY2); +          epoll_eperms [epoll_epermcnt++] = fd; +        } + +      return; +    }    fd_kill (EV_A_ fd); @@ -186,6 +202,18 @@ epoll_poll (EV_P_ ev_tstamp timeout)        epoll_eventmax = array_nextsize (sizeof (struct epoll_event), epoll_eventmax, epoll_eventmax + 1);        epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);      } + +  /* now add events for all fds where epoll fails, while select works... */ +  for (i = epoll_epermcnt; i--; ) +    { +      int fd = epoll_eperms [i]; +      unsigned char events = anfds [fd].events & (EV_READ | EV_WRITE); + +      if (anfds [fd].emask & EV_EMASK_EPERM && events) +        fd_event (EV_A_ fd, events); +      else +        epoll_eperms [i] = epoll_eperms [--epoll_epermcnt]; +    }  }  int inline_size @@ -217,6 +245,7 @@ void inline_size  epoll_destroy (EV_P)  {    ev_free (epoll_events); +  array_free (epoll_eperm, EMPTY);  }  void inline_size  | 
