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.