From 137492290cfc5d33496a47acc4152f4012a67bcf Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Tue, 13 Oct 2026 22:59:48 +0200 Subject: [PATCH] fs/vfs: Report POLLERR in the read and write sets of select(). select() put a descriptor with POLLERR only in exceptfds. A caller that asked only for readfds or writefds did not see the error: select() returned 0, also with no timeout, where 0 means that the timeout expired. POSIX says that a descriptor is ready for reading or writing when the call would not block, also when it would return an error. For example, a fifth thread that polls a pipe with CONFIG_DEV_PIPE_NPOLLWAITERS=4 gets POLLERR, and its select() with no timeout returned 0 at once. Report POLLERR in readfds and writefds, as Linux does. poll() reports POLLHUP and POLLERR also when they were not asked for, so set only the bits of the sets that the caller asked for. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli --- fs/vfs/fs_select.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/fs/vfs/fs_select.c b/fs/vfs/fs_select.c index d9bf848b26c1f..6815fee4321ce 100644 --- a/fs/vfs/fs_select.c +++ b/fs/vfs/fs_select.c @@ -245,11 +245,16 @@ int select(int nfds, FAR fd_set *readfds, FAR fd_set *writefds, * read condition. POLLHUP will be reported when no more data will * be available (such as when a connection is lost). In either * case, the read() can then be performed without blocking. + * + * POLLERR is a read and a write condition too: a read() or a + * write() then returns at once, with an error. poll() reports + * POLLHUP and POLLERR even when they were not asked for, so set + * only the bits that the caller asked for. */ - if (readfds) + if (readfds && (pollset[ndx].events & POLLIN) != 0) { - if (pollset[ndx].revents & (POLLIN | POLLHUP)) + if (pollset[ndx].revents & (POLLIN | POLLHUP | POLLERR)) { FD_SET(pollset[ndx].fd, readfds); ret++; @@ -258,9 +263,9 @@ int select(int nfds, FAR fd_set *readfds, FAR fd_set *writefds, /* Check for write conditions */ - if (writefds) + if (writefds && (pollset[ndx].events & POLLOUT) != 0) { - if (pollset[ndx].revents & (POLLOUT | POLLHUP)) + if (pollset[ndx].revents & (POLLOUT | POLLHUP | POLLERR)) { FD_SET(pollset[ndx].fd, writefds); ret++;