From d1d5acb9cfe37705e80195008bc98f2074b61563 Mon Sep 17 00:00:00 2001 From: visa Date: Tue, 9 May 2023 14:22:17 +0000 Subject: [PATCH] Don't return EPIPE from pipe kqfilter 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 | 12 +----------- sys/kern/sys_pipe.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index 9eccb48a3f1..e012d086ba6 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -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", diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 8958157f18c..b96d5081dba 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -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; -- 2.20.1