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>

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libc/port/sys/epoll.c
          +++ new/usr/src/lib/libc/port/sys/epoll.c
↓ open down ↓ 2 lines elided ↑ open up ↑
   3    3   * Common Development and Distribution License ("CDDL"), version 1.0.
   4    4   * You may only use this file in accordance with the terms of version
   5    5   * 1.0 of the CDDL.
   6    6   *
   7    7   * A full copy of the text of the CDDL should have accompanied this
   8    8   * source.  A copy of the CDDL is also available via the Internet at
   9    9   * http://www.illumos.org/license/CDDL.
  10   10   */
  11   11  
  12   12  /*
  13      - * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
       13 + * Copyright 2016 Joyent, Inc.
  14   14   */
  15   15  
  16   16  #include <sys/types.h>
  17   17  #include <sys/epoll.h>
  18   18  #include <sys/devpoll.h>
  19   19  #include <unistd.h>
  20   20  #include <errno.h>
  21   21  #include <fcntl.h>
  22   22  #include <poll.h>
  23   23  
↓ open down ↓ 83 lines elided ↑ open up ↑
 107  107          }
 108  108  
 109  109          return (fd);
 110  110  }
 111  111  
 112  112  int
 113  113  epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
 114  114  {
 115  115          dvpoll_epollfd_t epoll[2];
 116  116          uint32_t events, ev = 0;
 117      -        int i = 0;
      117 +        int i = 0, res;
 118  118  
 119  119          epoll[i].dpep_pollfd.fd = fd;
 120  120  
 121  121          switch (op) {
 122  122          case EPOLL_CTL_DEL:
 123  123                  ev = POLLREMOVE;
 124  124                  break;
 125  125  
 126  126          case EPOLL_CTL_MOD:
 127  127                  /*
↓ open down ↓ 30 lines elided ↑ open up ↑
 158  158  
 159  159                  epoll[i].dpep_data = event->data.u64;
 160  160                  break;
 161  161  
 162  162          default:
 163  163                  errno = EOPNOTSUPP;
 164  164                  return (-1);
 165  165          }
 166  166  
 167  167          epoll[i].dpep_pollfd.events = ev;
      168 +retry:
      169 +        res = write(epfd, epoll, sizeof (epoll[0]) * (i + 1));
 168  170  
 169      -        return (write(epfd, epoll, sizeof (epoll[0]) * (i + 1)) == -1 ? -1 : 0);
      171 +        if (res == -1) {
      172 +                if (errno == EINTR) {
      173 +                        /*
      174 +                         * Linux does not document EINTR as an allowed error
      175 +                         * for epoll_ctl.  The write must be retried if it is
      176 +                         * not done automatically via SA_RESTART.
      177 +                         */
      178 +                        goto retry;
      179 +                }
      180 +                if (errno == ELOOP) {
      181 +                        /*
      182 +                         * Convert the specific /dev/poll error about an fd
      183 +                         * loop into what is expected from the Linux epoll
      184 +                         * interface.
      185 +                         */
      186 +                        errno = EINVAL;
      187 +                }
      188 +                return (-1);
      189 +        }
      190 +        return (0);
 170  191  }
 171  192  
 172  193  int
 173  194  epoll_wait(int epfd, struct epoll_event *events,
 174  195      int maxevents, int timeout)
 175  196  {
 176  197          struct dvpoll arg;
 177  198  
 178  199          if (maxevents <= 0) {
 179  200                  errno = EINVAL;
↓ open down ↓ 28 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX