mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
io_uring/waitid: return -EAGAIN for a non-blocking pidfd
IORING_OP_WAITID on a pidfd opened with PIDFD_NONBLOCK completes at once with res 0 and an all-zero siginfo when the child has not changed state, although WNOHANG was not requested. waitid(2) with the same arguments fails with -EAGAIN. An application that submits the same request it would pass to waitid(2) and treats res 0 as "the child changed state" sees si_signo 0 and si_pid 0 instead. kernel_waitid_prepare() turns an O_NONBLOCK pidfd into WNOHANG in wo->wo_flags. kernel_waitid() then maps the resulting 0 return to -EAGAIN when the caller did not ask for WNOHANG itself, as added in commitba7d25f3df("exit: support non-blocking pidfds"). io_waitid() uses kernel_waitid_prepare() and __do_wait() directly and does not do that mapping. Do the same check in io_waitid() before completing the request. Only the inline path needs it: with WNOHANG set, __do_wait() never returns -ERESTARTSYS, so such a request is never armed on the wait queue. Reproduced on x86_64 under QEMU: with a PIDFD_NONBLOCK pidfd of a running child and options = WEXITED, waitid(2) fails with -EAGAIN and IORING_OP_WAITID completed with res 0 before the change; it completes with res -EAGAIN after it. Fixes:f31ecf671d("io_uring: add IORING_OP_WAITID support") Assisted-by: LLM Signed-off-by: Nickolai Zeldovich <nickolai@csail.mit.edu> Link: https://patch.msgid.link/20261018025824.799245-1-nickolai@csail.mit.edu Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
96262cfab5
commit
c82621eb2c
|
|
@ -10,6 +10,7 @@
|
|||
#include <linux/io_uring.h>
|
||||
|
||||
#include <uapi/linux/io_uring.h>
|
||||
#include <uapi/linux/wait.h>
|
||||
|
||||
#include "io_uring.h"
|
||||
#include "cancel.h"
|
||||
|
|
@ -368,6 +369,9 @@ int io_waitid(struct io_kiocb *req, unsigned int issue_flags)
|
|||
|
||||
hlist_del_init(&req->hash_node);
|
||||
io_waitid_remove_wq(req);
|
||||
/* a non-blocking pidfd implies WNOHANG, report it as waitid(2) does */
|
||||
if (!ret && !(iw->options & WNOHANG) && (iwa->wo.wo_flags & WNOHANG))
|
||||
ret = -EAGAIN;
|
||||
ret = io_waitid_finish(req, ret);
|
||||
|
||||
io_ring_submit_unlock(ctx, issue_flags);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user