Skip to content

Stop ppoll calling a live descriptor invalid - #316

Merged
jserv merged 1 commit into
sysprog21:mainfrom
xalestar:ppoll-pollnval
Aug 21, 2026
Merged

Stop ppoll calling a live descriptor invalid#316
jserv merged 1 commit into
sysprog21:mainfrom
xalestar:ppoll-pollnval

Conversation

@xalestar

@xalestarxalestar commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

ppoll tells the guest a descriptor is invalid when macOS poll() will not put it on a kqueue: /dev/null, /dev/zero, /dev/urandom, directory descriptors and epoll descriptors are all open and, on Linux, ready.


Summary by cubic

Stops ppoll on macOS from reporting POLLNVAL for live descriptors, matching Linux readiness for devices, directories, and epoll fds. Old: we propagated host poll()’s POLLNVAL; New: detect host-refused entries once and compute their readiness via select(), keeping POLLNVAL only for invalid fds.

  • Detect POLLNVAL-only entries once, drop them from the poll set, and re-evaluate via select() (zero timeout) each loop; a refused entry causes a single immediate restart, and calls without them make no extra syscalls.
  • Return readiness for always-ready devices and directories; epoll fds report idle vs ready correctly; do not interfere with other pollable entries; honor timeouts and wakeups; do not spin.
  • Preserve POLLNVAL for closed/invalid guest fds; other error paths unchanged.
  • Treat write readiness as POLLOUT|POLLWRBAND so guest POLLWRNORM is honored; for fds ≥ FD_SETSIZE, return requested readiness bits to mirror Linux.
  • Tests cover devices/directories readiness, epoll idle/ready, closed fd retaining POLLNVAL, blocking wait alongside an epoll fd, and POLLWRNORM on /dev/null.

Written for commit f0c25bf. Summary will update on new commits.

Review in cubic

cubic-dev-ai[bot]

This comment was marked as resolved.

macOS poll() answers POLLNVAL for any descriptor it will not put on a
kqueue: /dev/null, /dev/zero, /dev/random, /dev/urandom, directories,
and kqueue descriptors themselves. sys_ppoll copies host revents to the
guest unchanged, so a guest polling an open /dev/null is told the
descriptor is closed. Linux polls every one of them: the character
devices and directories through the default always-ready mask, an epoll
descriptor through its own readiness.
POLLNVAL is not a vague error at the call site. A program that redirects
its output to /dev/null and polls it reads POLLNVAL as a descriptor that
no longer exists, closes it and drops it from the set, so the guest
tears down a working descriptor of its own accord.
macOS select() accepts every descriptor its poll() refuses, and reports
real readiness for a kqueue descriptor rather than a fixed answer.
poll_eval_unpollable() evaluates those entries through select(). They
leave the poll set on the pass that exposes them and stay out; a refused
entry makes poll() return at once, so that single restart waits for
nothing, and a call holding none of them issues no extra syscall.
Entries that sys_ppoll marked need_pollnval keep their POLLNVAL, so a
closed guest fd still reports one.
A guest's events reach the host untranslated, and Linux POLLWRNORM is
the bit macOS spells POLLWRBAND, so the write test names the pair rather
than POLLOUT alone.
Verified: tests/test-poll.c carries five new cases and reports 19
passed, 0 failed both under elfuse and inside the qemu-system-aarch64
reference VM. The probe that exposed this returns revents=0x05
(POLLIN|POLLOUT) for /dev/null, /dev/zero, /dev/urandom and a directory
descriptor on both sides. make check is clean, and tests/test-matrix.sh
all stays within baseline with zero failures: elfuse-aarch64 255 passed,
qemu-aarch64 234 passed, elfuse-x86_64 78 passed.
@jserv
jserv merged commit dbe0dbe into sysprog21:mainAug 21, 2026
14 checks passed
@xalestar
xalestar deleted the ppoll-pollnval branch August 21, 2026 12:18
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@xalestar@jserv