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>

@@ -22,11 +22,11 @@
 /*        All Rights Reserved   */
 
 
 /*
  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2014, Joyent, Inc. All rights reserved.
+ * Copyright 2017 Joyent, Inc.
  */
 
 #include <sys/types.h>
 #include <sys/sysmacros.h>
 #include <sys/param.h>

@@ -8172,15 +8172,11 @@
  * Note: POLLRDDATA assumes that synch streams only return messages with
  * an M_DATA attached (i.e. not messages consisting of only
  * an M_PROTO/M_PCPROTO part).
  */
 int
-strpoll(
-        struct stdata *stp,
-        short events_arg,
-        int anyyet,
-        short *reventsp,
+strpoll(struct stdata *stp, short events_arg, int anyyet, short *reventsp,
         struct pollhead **phpp)
 {
         int events = (ushort_t)events_arg;
         int retevents = 0;
         mblk_t *mp;

@@ -8314,12 +8310,11 @@
                                 retevents |= normevents;
                         else
                                 retevents |= (events & (POLLIN | POLLRDBAND));
                         break;
                 }
-                if (! (retevents & normevents) &&
-                    (stp->sd_wakeq & RSLEEP)) {
+                if (!(retevents & normevents) && (stp->sd_wakeq & RSLEEP)) {
                         /*
                          * Sync stream barrier read queue has data.
                          */
                         retevents |= normevents;
                 }

@@ -8326,23 +8321,15 @@
                 /* Treat eof as normal data */
                 if (sd_flags & STREOF)
                         retevents |= normevents;
         }
 
-        *reventsp = (short)retevents;
-        if (retevents && !(events & POLLET)) {
-                if (headlocked)
-                        mutex_exit(&stp->sd_lock);
-                return (0);
-        }
-
         /*
-         * If poll() has not found any events yet, set up event cell
-         * to wake up the poll if a requested event occurs on this
-         * stream.  Check for collisions with outstanding poll requests.
+         * Pass back a pollhead if no events are pending or if edge-triggering
+         * has been configured on this resource.
          */
-        if (!anyyet) {
+        if ((retevents == 0 && !anyyet) || (events & POLLET)) {
                 *phpp = &stp->sd_pollist;
                 if (headlocked == 0) {
                         if (polllock(&stp->sd_pollist, &stp->sd_lock) != 0) {
                                 *reventsp = POLLNVAL;
                                 return (0);

@@ -8349,10 +8336,12 @@
                         }
                         headlocked = 1;
                 }
                 stp->sd_rput_opt |= SR_POLLIN;
         }
+
+        *reventsp = (short)retevents;
         if (headlocked)
                 mutex_exit(&stp->sd_lock);
         return (0);
 }