Bug 248440 - kqueue(2): kevent not returning full pipes registered with EVFILT_WRITE on read end closure
Summary: kqueue(2): kevent not returning full pipes registered with EVFILT_WRITE on re...
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 12.1-RELEASE
Hardware: Any Any
: --- Affects Some People
Assignee: freebsd-bugs (Nobody)
Keywords: needs-qa
Depends on:
Reported: 2020-08-02 23:20 UTC by larkinconr
Modified: 2020-08-04 16:14 UTC (History)
2 users (show)

See Also:
koobs: maintainer-feedback? (markj)

test program to reproduce bug via filling/monitoring stdout (1.71 KB, text/plain)
2020-08-02 23:20 UTC, larkinconr
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description larkinconr 2020-08-02 23:20:02 UTC
Created attachment 216970 [details]
test program to reproduce bug via filling/monitoring stdout

When using kevent to monitor the write end of a pipe for writability via EVFILT_WRITE, if the pipe is full when the read end is closed, an event is not returned. I would expect an event with EV_EOF set to be returned. Note that this does not seem to reproduce with sockets or named pipes (fifos), those return an event with EV_EOF set just fine in this situation.

I'm attaching a sample program that verifies stdout is a pipe and then attempts to fill  it with data, then waits for an event with EVFILT_WRITE for stdout. If you pipe this to  some program that doesn't read stdin, for instance sleep(1), the pipeline hangs forever. Notably, if you instead redirect its output to a named pipe and have sleep "read" the named pipe with shell redirection, the program *does* receive an event for stdout with EV_EOF set once sleep exits.

I originally detected this with a test case that creates a pipe via pipe(2) in process, so testing with socketpair(2) was convenient, but it used threads and other infrastructure etc so I wrote a new test program. But I just want to mention that because it would seem to exclude some weird interaction with my shell etc.

Example test case using the attached kqwrite.c:

$ ./kqwrite | /bin/sleep 1 # hangs forever
$ mkfifo dummy; /bin/sleep 1 < dummy &; ./kqwrite > dummy # returns EV_EOF:
[1] 1734
kevent returned 1
        1 -2 32768 0 0 0x0
[1]  + done       /bin/sleep 1 < dummy
Comment 1 Kubilay Kocak freebsd_committer freebsd_triage 2020-08-02 23:37:06 UTC
^Triage: Request feedback from markj per base r360380 base r360379 base r360378, which may be related (or resolve) this issue.

@Mark If this is indeed resolved, could you please close this a duplicate of the relevant issue ID (if this report matches a previously reported one)
Comment 2 Mark Johnston freebsd_committer 2020-08-04 16:11:35 UTC
Indeed, I believe this is fixed in head and on stable/12 (so it will be fixed in 12.2).  The test case does not hang for me on head:

$ ./kqwrite | sleep 1
kevent returned 1
        1 -2 32768 0 0 0x0
Comment 3 Mark Johnston freebsd_committer 2020-08-04 16:14:20 UTC
It should be r360379 that fixed this.  The referenced PRs have to do with named pipes, which are not related to this particular report, so I'll just mark the bug fixed without duping.  Please feel free to comment further or re-open if necessary.