Print this page
8634 epoll fails to wake on certain edge-triggered conditions
8635 epoll should not emit POLLNVAL
8636 recursive epoll should emit EPOLLRDNORM
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Igor Kozhukhov <igor@dilos.org>

@@ -23,11 +23,11 @@
 
 
 /*
  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
- * Copyright 2015 Joyent, Inc.
+ * Copyright 2017 Joyent, Inc.
  */
 
 /*
  * Generic vnode operations.
  */

@@ -414,10 +414,21 @@
 /* ARGSUSED */
 int
 fs_poll(vnode_t *vp, short events, int anyyet, short *reventsp,
     struct pollhead **phpp, caller_context_t *ct)
 {
+        /*
+         * Reject all attempts for edge-triggered polling.  These should only
+         * occur when regular files are added to a /dev/poll handle which is in
+         * epoll mode.  The Linux epoll does not allow epoll-ing on regular
+         * files at all, so rejecting EPOLLET requests is congruent with those
+         * expectations.
+         */
+        if (events & POLLET) {
+                return (EPERM);
+        }
+
         *reventsp = 0;
         if (events & POLLIN)
                 *reventsp |= POLLIN;
         if (events & POLLRDNORM)
                 *reventsp |= POLLRDNORM;

@@ -425,11 +436,19 @@
                 *reventsp |= POLLRDBAND;
         if (events & POLLOUT)
                 *reventsp |= POLLOUT;
         if (events & POLLWRBAND)
                 *reventsp |= POLLWRBAND;
-        *phpp = !anyyet && !*reventsp ? &fs_pollhd : (struct pollhead *)NULL;
+        /*
+         * Emitting a pollhead without the intention of issuing pollwakeup()
+         * calls against it is a recipe for trouble.  It's only acceptable in
+         * this case since the above logic matches practically all useful
+         * events.
+         */
+        if (*reventsp == 0 && !anyyet) {
+                *phpp = &fs_pollhd;
+        }
         return (0);
 }
 
 /*
  * POSIX pathconf() support.