Preserve pipe select(2) semantics when the other end of the pipe is gone.
authoranton <anton@openbsd.org>
Fri, 22 Oct 2021 05:00:26 +0000 (05:00 +0000)
committeranton <anton@openbsd.org>
Fri, 22 Oct 2021 05:00:26 +0000 (05:00 +0000)
In preparation for implementing select(2) on top of kqueue.

ok mpi@

sys/kern/sys_pipe.c

index f9bae89..fa85571 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sys_pipe.c,v 1.126 2020/12/30 17:02:32 visa Exp $     */
+/*     $OpenBSD: sys_pipe.c,v 1.127 2021/10/22 05:00:26 anton Exp $    */
 
 /*
  * Copyright (c) 1996 John S. Dyson
@@ -890,16 +890,27 @@ pipe_kqfilter(struct file *fp, struct knote *kn)
                kn->kn_hook = rpipe;
                klist_insert_locked(&rpipe->pipe_sel.si_note, kn);
                break;
-       case EVFILT_WRITE:
+       case EVFILT_WRITE: {
+               struct pipe *kpipe = wpipe;
+
                if (wpipe == NULL) {
                        /* other end of pipe has been closed */
-                       error = EPIPE;
-                       break;
+                       if (kn->kn_flags & __EV_POLL) {
+                               /*
+                                * select(2) semantics requires the pipe to
+                                * become ready only to deliver EPIPE.
+                                */
+                               kpipe = rpipe;
+                       } else {
+                               error = EPIPE;
+                               break;
+                       }
                }
                kn->kn_fop = &pipe_wfiltops;
-               kn->kn_hook = wpipe;
-               klist_insert_locked(&wpipe->pipe_sel.si_note, kn);
+               kn->kn_hook = kpipe;
+               klist_insert_locked(&kpipe->pipe_sel.si_note, kn);
                break;
+       }
        default:
                error = EINVAL;
        }