diff options
| author | Daan De Meyer <daan@amutable.com> | 2026-10-27 16:09:37 +0100 |
|---|---|---|
| committer | Jens Axboe <axboe@kernel.dk> | 2026-10-27 10:44:13 -0600 |
| commit | 71537ed811107c514c0342e98902d489d6d2b7cd (patch) | |
| tree | 77a647d99ff8b5dad999e56262322ecb20f6de50 /tools/lib/python/kdoc/python_version.py | |
| parent | 4a93427e99a8524f3612f29ec8bc0da5f8435a51 (diff) | |
io_uring/net: don't retry a non-blocking connect() that fails with -EAGAIN
IORING_OP_CONNECT on an O_NONBLOCK AF_UNIX stream socket retries a
connect that fails with -EAGAIN because the listener's backlog is full.
Polling the client socket doesn't help: an unconnected stream socket
reports EPOLLOUT and EPOLLHUP right away, before the backlog drains. So
io_uring retries the connect until the apoll retry limit is hit, then
punts the request to io-wq. With a full backlog, io_connect() runs 128
times in the submitting task and once more in a new io-wq worker. That
worker stays in the task's thread group, so a later
unshare(CLONE_NEWUSER) fails with -EINVAL.
None of this changes the result. __sys_connect_file() adds the socket's
own O_NONBLOCK to every attempt, so the attempt from io-wq fails with
-EAGAIN as well. That -EAGAIN becomes the CQE result, and connect(2)
returns the same -EAGAIN.
Let's complete the request with -EAGAIN right away when the socket has
O_NONBLOCK set, like connect(2) does. io_accept() already completes
-EAGAIN this way for IORING_ACCEPT_DONTWAIT. -EINPROGRESS still waits
for the connection to complete. A blocking socket still ends up in
io-wq, where the connect sleeps until the listener accepts.
Fixes: f8e85cf255ad ("io_uring: add support for IORING_OP_CONNECT")
Signed-off-by: Daan De Meyer <daan@amutable.com>
Link: https://patch.msgid.link/20261027-b4-io-uring-connect-eagain-v1-1-f4e3aaaa49ee@amutable.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'tools/lib/python/kdoc/python_version.py')
0 files changed, 0 insertions, 0 deletions
