Print this page
OS-5518 devpoll write feigns success in the face of EINTR
OS-5520 epoll_ctl not allowed to emit EINTR
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Bryan Cantrill <bryan@joyent.com>
OS-5459 epoll_ctl should throw EINVAL for loops
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
        
*** 8,18 ****
   * source.  A copy of the CDDL is also available via the Internet at
   * http://www.illumos.org/license/CDDL.
   */
  
  /*
!  * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
   */
  
  #include <sys/types.h>
  #include <sys/epoll.h>
  #include <sys/devpoll.h>
--- 8,18 ----
   * source.  A copy of the CDDL is also available via the Internet at
   * http://www.illumos.org/license/CDDL.
   */
  
  /*
!  * Copyright 2016 Joyent, Inc.
   */
  
  #include <sys/types.h>
  #include <sys/epoll.h>
  #include <sys/devpoll.h>
*** 112,122 ****
  int
  epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
  {
          dvpoll_epollfd_t epoll[2];
          uint32_t events, ev = 0;
!         int i = 0;
  
          epoll[i].dpep_pollfd.fd = fd;
  
          switch (op) {
          case EPOLL_CTL_DEL:
--- 112,122 ----
  int
  epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
  {
          dvpoll_epollfd_t epoll[2];
          uint32_t events, ev = 0;
!         int i = 0, res;
  
          epoll[i].dpep_pollfd.fd = fd;
  
          switch (op) {
          case EPOLL_CTL_DEL:
*** 163,174 ****
                  errno = EOPNOTSUPP;
                  return (-1);
          }
  
          epoll[i].dpep_pollfd.events = ev;
  
!         return (write(epfd, epoll, sizeof (epoll[0]) * (i + 1)) == -1 ? -1 : 0);
  }
  
  int
  epoll_wait(int epfd, struct epoll_event *events,
      int maxevents, int timeout)
--- 163,195 ----
                  errno = EOPNOTSUPP;
                  return (-1);
          }
  
          epoll[i].dpep_pollfd.events = ev;
+ retry:
+         res = write(epfd, epoll, sizeof (epoll[0]) * (i + 1));
  
!         if (res == -1) {
!                 if (errno == EINTR) {
!                         /*
!                          * Linux does not document EINTR as an allowed error
!                          * for epoll_ctl.  The write must be retried if it is
!                          * not done automatically via SA_RESTART.
!                          */
!                         goto retry;
!                 }
!                 if (errno == ELOOP) {
!                         /*
!                          * Convert the specific /dev/poll error about an fd
!                          * loop into what is expected from the Linux epoll
!                          * interface.
!                          */
!                         errno = EINVAL;
!                 }
!                 return (-1);
!         }
!         return (0);
  }
  
  int
  epoll_wait(int epfd, struct epoll_event *events,
      int maxevents, int timeout)