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>

@@ -38,10 +38,11 @@
  * "Header: bpf.c,v 1.67 96/09/26 22:00:52 leres Exp ";
  */
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
+ * Copyright 2017 Joyent, Inc.
  */
 
 /*
  * The BPF implements the following access controls for zones attempting
  * to read and write data. Writing of data requires that the net_rawaccess

@@ -1394,24 +1395,25 @@
         mutex_exit(&d->bd_lock);
 
         return (0);
 }
 
-/*
- * Support for poll() system call
- *
- * Return true iff the specific operation will not block indefinitely - with
- * the assumption that it is safe to positively acknowledge a request for the
- * ability to write to the BPF device.
- * Otherwise, return false but make a note that a selnotify() must be done.
- */
+/* ARGSUSED */
 int
 bpfchpoll(dev_t dev, short events, int anyyet, short *reventsp,
     struct pollhead **phpp)
 {
         struct bpf_d *d = bpf_dev_get(getminor(dev));
 
+        /*
+         * Until this driver is modified to issue proper pollwakeup() calls on
+         * its pollhead, edge-triggered polling is not allowed.
+         */
+        if (events & POLLET) {
+                return (EPERM);
+        }
+
         if (events & (POLLIN | POLLRDNORM)) {
                 /*
                  * An imitation of the FIONREAD ioctl code.
                  */
                 mutex_enter(&d->bd_lock);

@@ -1418,13 +1420,17 @@
                 if (d->bd_hlen != 0 ||
                     ((d->bd_immediate || d->bd_state == BPF_TIMED_OUT) &&
                     d->bd_slen != 0)) {
                         *reventsp |= events & (POLLIN | POLLRDNORM);
                 } else {
+                        /*
+                         * Until the bpf driver has been updated to include
+                         * adequate pollwakeup() logic, no pollhead will be
+                         * emitted here, preventing the resource from being
+                         * cached by poll()/devpoll/epoll.
+                         */
                         *reventsp = 0;
-                        if (!anyyet)
-                                *phpp = &d->bd_poll;
                         /* Start the read timeout if necessary */
                         if (d->bd_rtout > 0 && d->bd_state == BPF_IDLE) {
                                 bpf_clear_timeout(d);
                                 /*
                                  * Only allow the timeout to be set once.