Set POLLHUP even if no valid events were specified as per POSIX.
authormillert <millert@openbsd.org>
Sun, 10 May 2015 22:35:38 +0000 (22:35 +0000)
committermillert <millert@openbsd.org>
Sun, 10 May 2015 22:35:38 +0000 (22:35 +0000)
Since we use the poll backend for select(2), care must be taken not
to set the fd's bit in writefds in this case.  A kernel-only flag,
POLLNOHUP, is used by selscan() to tell the poll backend not to
return POLLHUP on EOF.  This is currently only used by fifo_poll().
The fifofs regress now passes.  OK guenther@

sys/kern/sys_generic.c
sys/miscfs/fifofs/fifo_vnops.c
sys/sys/poll.h

index 57b1813..cefcf9f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sys_generic.c,v 1.97 2015/04/30 09:20:51 mpi Exp $    */
+/*     $OpenBSD: sys_generic.c,v 1.98 2015/05/10 22:35:38 millert Exp $        */
 /*     $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $     */
 
 /*
@@ -712,7 +712,7 @@ selscan(struct proc *p, fd_set *ibits, fd_set *obits, int nfd, int ni,
        fd_mask bits;
        struct file *fp;
        int n = 0;
-       static const int flag[3] = { POLLIN, POLLOUT, POLLPRI };
+       static const int flag[3] = { POLLIN, POLLOUT|POLLNOHUP, POLLPRI };
 
        for (msk = 0; msk < 3; msk++) {
                fd_set *pibits = (fd_set *)&cibits[msk*ni];
@@ -940,8 +940,10 @@ doppoll(struct proc *p, struct pollfd *fds, u_int nfds,
        if ((error = copyin(fds, pl, sz)) != 0)
                goto bad;
 
-       for (i = 0; i < nfds; i++)
+       for (i = 0; i < nfds; i++) {
+               pl[i].events &= ~POLLNOHUP;
                pl[i].revents = 0;
+       }
 
        if (tsp != NULL) {
                getnanouptime(&rts);
index 41a6f8a..4d6a0d7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: fifo_vnops.c,v 1.46 2015/05/05 20:14:10 millert Exp $ */
+/*     $OpenBSD: fifo_vnops.c,v 1.47 2015/05/10 22:35:39 millert Exp $ */
 /*     $NetBSD: fifo_vnops.c,v 1.18 1996/03/16 23:52:42 christos Exp $ */
 
 /*
@@ -296,28 +296,28 @@ fifo_poll(void *v)
        int revents = 0;
 
        /*
-        * Just return if there are no supported events specified,
         * FIFOs don't support out-of-band or high priority data.
         */
        if (ap->a_fflag & FREAD)
                events |= ap->a_events & (POLLIN | POLLRDNORM);
        if (ap->a_fflag & FWRITE)
                events |= ap->a_events & (POLLOUT | POLLWRNORM);
-       if (events == 0)
-               return (0);
 
        if (events & (POLLIN | POLLRDNORM)) {
                if (soreadable(rso))
                        revents |= events & (POLLIN | POLLRDNORM);
        }
        /* NOTE: POLLHUP and POLLOUT/POLLWRNORM are mutually exclusive */
-       if (rso->so_state & SS_ISDISCONNECTED) {
+       if ((rso->so_state & SS_ISDISCONNECTED) && !(ap->a_events & POLLNOHUP)) {
                revents |= POLLHUP;
        } else if (events & (POLLOUT | POLLWRNORM)) {
                if (sowriteable(wso))
                        revents |= events & (POLLOUT | POLLWRNORM);
        }
        if (revents == 0) {
+               /* We want to return POLLHUP even if no valid events set. */
+               if (events == 0 && !(ap->a_events & POLLNOHUP))
+                       events = POLLIN;
                if (events & (POLLIN | POLLRDNORM)) {
                        selrecord(ap->a_p, &rso->so_rcv.sb_sel);
                        rso->so_rcv.sb_flagsintr |= SB_SEL;
index 89d77d3..8667b99 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: poll.h,v 1.13 2013/04/29 18:35:07 guenther Exp $ */
+/*     $OpenBSD: poll.h,v 1.14 2015/05/10 22:35:38 millert Exp $ */
 
 /*
  * Copyright (c) 1996 Theo de Raadt
@@ -47,6 +47,9 @@ typedef unsigned int  nfds_t;
 #define POLLWRNORM      POLLOUT
 #define        POLLRDBAND      0x0080
 #define        POLLWRBAND      0x0100
+#ifdef _KERNEL
+#define        POLLNOHUP       0x1000          /* internal use only */
+#endif
 
 #define INFTIM         (-1)