Don't return EPIPE from pipe kqfilter
authorvisa <visa@openbsd.org>
Tue, 9 May 2023 14:22:17 +0000 (14:22 +0000)
committervisa <visa@openbsd.org>
Tue, 9 May 2023 14:22:17 +0000 (14:22 +0000)
Proceed with the registration of an EVFILT_WRITE filter even if the
pipe's other end has been closed, instead of failing with error EPIPE.
The filter will trigger immediately. This reduces the possible outcomes
when a kevent(2) call and a close(2) call race on the different ends
of a pipe.

This fixes a failure of lang/ghc unit test as reported by gnezdo@.

OK gnezdo@ mpi@

sys/kern/sys_generic.c
sys/kern/sys_pipe.c

index 9eccb48..e012d08 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sys_generic.c,v 1.155 2023/02/25 09:55:46 mvs Exp $   */
+/*     $OpenBSD: sys_generic.c,v 1.156 2023/05/09 14:22:17 visa Exp $  */
 /*     $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $     */
 
 /*
@@ -769,12 +769,6 @@ pselregister(struct proc *p, fd_set *pibits[3], fd_set *pobits[3], int nfd,
                                                 * __EV_SELECT */
                                        error = 0;
                                        break;
-                               case EPIPE:     /* Specific to pipes */
-                                       KASSERT(kev.filter == EVFILT_WRITE);
-                                       FD_SET(kev.ident, pobits[1]);
-                                       (*ncollected)++;
-                                       error = 0;
-                                       break;
                                case ENXIO:     /* Device has been detached */
                                default:
                                        goto bad;
@@ -1073,10 +1067,6 @@ again:
                                goto again;
                        }
                        break;
-               case EPIPE:     /* Specific to pipes */
-                       KASSERT(kevp->filter == EVFILT_WRITE);
-                       pl->revents |= POLLHUP;
-                       break;
                default:
                        DPRINTFN(0, "poll err %lu fd %d revents %02x serial"
                            " %lu filt %d ERROR=%d\n",
index 8958157..b96d508 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sys_pipe.c,v 1.145 2023/02/12 10:41:00 mvs Exp $      */
+/*     $OpenBSD: sys_pipe.c,v 1.146 2023/05/09 14:22:17 visa Exp $     */
 
 /*
  * Copyright (c) 1996 John S. Dyson
@@ -857,9 +857,13 @@ pipe_kqfilter(struct file *fp, struct knote *kn)
                break;
        case EVFILT_WRITE:
                if (wpipe == NULL) {
-                       /* other end of pipe has been closed */
-                       error = EPIPE;
-                       break;
+                       /*
+                        * The other end of the pipe has been closed.
+                        * Since the filter now always indicates a pending
+                        * event, attach the knote to the current side
+                        * to proceed with the registration.
+                        */
+                       wpipe = rpipe;
                }
                kn->kn_fop = &pipe_wfiltops;
                kn->kn_hook = wpipe;