kqueue/kernel/t_pipe: Fix newly failing test.
If the read side of a pipe has been closed, then for the write side:
- poll will set POLLOUT, not POLLNVAL (nor fail with EBADF), and
- select will report writable, not fail with EBADF,
because the write side is immediately writable and will fail with
EPIPE/SIGPIPE -- it won't block if you try to write.
So surely kqueue with EVFILT_WRITE should simply report immediately
writable too, not fail with EBADF. And that is what I caused to
happen by simplifying and clarifying the code and fixing various edge
cases. (The bad response that this test was added to check is a
kernel crash on null pointer dereference; that, fortunately, has not
regressed.)
PR kern/59056: poll POLLHUP bugs
xorgproto: update to 2026.1.
The primary practical effect of this release is making a number of
new keysym definitions available to X11 clients & servers.
Alan Coopersmith (3):
gitlab CI: drop the ci-fairy check-mr job
Ensure text files end with a newline
xorgproto 2026.1
Jasmine Tang (1):
COPYING-xextproto: drop stale NCD notice of removed LBX headers
Pierre Le Marre (7):
keysyms: Added Unicode annotations for phone numeric keys
keysyms: Add keys from kernel 6.18
keysyms: Promote ISO_Group_Shift to canonical name
keysysm: Added SSHARP
[6 lines not shown]
pipe(2): Don't cv_wait_sig in a loop without breaking on signal.
If a signal does arrive, it will turn into a busy wait! Not helpful.
But this wait should be limited to scheduling delays for other
threads anyway, not for general I/O, so there's no need to be
interruptible by a signal.
Prompted by:
PR kern/59056: poll POLLHUP bugs
pipe(2): Restructure select/poll/kqueue records.
1. When a thread is waiting on an endpoint of a pipe, have it wait on
_that endpoint_ (i.e., cv_wait or selrecord), not on the other
endpoint sometimes depending on the direction of the I/O.
2. Make poll(2) on the writer side of a pipe wake with POLLERR when
the reader side is closed, because write would return immediately,
and fail with EPIPE/SIGPIPE. See also:
https://mail-index.NetBSD.org/tech-kern/2026/09/21/msg031255.html
(In contrast, for the other way around, when the writer side of a
pipe is closed, poll(2) on the reader is already defined to wake
with POLLHUP, and while read would return immediately, it will not
_fail_; it will simply report EOF, so there is no justification
for POLLERR in that direction.)
3. For EVFILT_READ, require the reader side of a pipe; likewise, for
[6 lines not shown]
pipe(2): Simplify PIPE_RESTART handling.
Now that it applies to each side independently, we can just make it
final, because new I/O operations are not allowed on an file that has
had its .fo_restart called. Makes reasoning about all this easier.
XXX Consider renaming PIPE_RESTART to PIPE_CLOSING: the .fo_restart
operation means the file is irreversibly destined to be closed soon
and just needs any pending I/O on it to be interrupted and fail
promptly so we can finally close the file.
Preparation for:
PR kern/59056: poll POLLHUP bugs
pipe(2): Make pipe sides a little more symmetric.
1. When reading from or writing to a pipe, busy _this side_ of the
pipe, not the other side.
2. In pipeclose, all operations on _this side_ of the pipe have already
quiesced. But operations on the other side may not have. So wait
for the _other side_ to be unbusied before disconnecting the peer
(changing ppipe->pipe_peer from pipe to NULL).
With (1) and (2) we can prove a simple property that makes reasoning
about this code easier: If a pipe is busy, its peer pointer is stable
even across cv_wait on the pipe lock. Without these changes I'm not
sure I could prove that property (though I haven't exhibited a
reproducer for any issues arising from its failure).
3. Make write wait on wpipe->pipe_wcv, and make read wait on
rpipe->pipe_rcv, consistently, so that any waiters on one side of a
pipe will always be waiting on one of _that side's_ condvars.
[17 lines not shown]
pipe(2): Fix wakeup of pending writers on close of write side.
The job of pipe_restart is to wake any pending I/O operations on the
file when it is about to be closed. New references cannot be taken
for new I/O operations; once all existing references are drained, the
system calls pipe_close.
What pipe_restart did was to wake pipe->pipe_rcv and pipe->pipe_wcv.
But the condvars of _which pipe_?
After renaming the variables to match reality, it becomes clear that
wpipe->pipe_wcv and wpipe->pipe_rcv are never used -- instead,
pipe_read waits for rpipe->pipe_rcv, and pipe_write waits for
rpipe->pipe_wcv. So pipe_restart on the write side of a pipe woke
wpipe->pipe_rcv and wpipe->pipe_wcv, which nothing was waiting for,
and failed to wake rpipe->pipe_rcv or rpipe->pipe_wcv.
(Perhaps we should just have a single struct pipe::pipe_cv member,
and have pipe_read use rpipe->pipe_cv and pipe_write use
[4 lines not shown]