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>

@@ -19,10 +19,11 @@
  * CDDL HEADER END
  */
 
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2017 Joyent, Inc.
  */
 
 #include <sys/types.h>
 #include <sys/t_lock.h>
 #include <sys/param.h>

@@ -1092,29 +1093,25 @@
          * Check for errors
          */
         if (so->so_error != 0 &&
             ((POLLIN|POLLRDNORM|POLLOUT) & origevents)  != 0) {
                 *reventsp = (POLLIN|POLLRDNORM|POLLOUT) & origevents;
-                return (0);
+                goto done;
         }
 
         *reventsp = 0;
+        if (so->so_type != SOCK_STREAM) {
+                goto done;
+        }
 
         /*
-         * Don't mark socket as writable until TX queued data is
-         * below watermark.
+         * Don't mark socket writable until TX queued data is below watermark.
          */
-        if (so->so_type == SOCK_STREAM) {
-                if (sdp_polldata(
-                    (struct sdp_conn_struct_t *)so->so_proto_handle,
+        if (sdp_polldata((struct sdp_conn_struct_t *)so->so_proto_handle,
                     SDP_XMIT)) {
                         *reventsp |= POLLOUT & events;
                 }
-        } else {
-                *reventsp = 0;
-                goto done;
-        }
 
         if (sdp_polldata((struct sdp_conn_struct_t *)so->so_proto_handle,
             SDP_READ)) {
                 *reventsp |= (POLLIN|POLLRDNORM) & events;
         }

@@ -1122,11 +1119,11 @@
         if ((so_state & SS_CANTRCVMORE) || (so->so_acceptq_len > 0)) {
                 *reventsp |= (POLLIN|POLLRDNORM) & events;
         }
 
 done:
-        if (!*reventsp && !anyyet) {
+        if ((*reventsp == 0 && !anyyet) || (events & POLLET)) {
                 *phpp = &so->so_poll_list;
         }
 
         return (0);
 }