Closed EmilyPetersonM closed 3 weeks ago
kernel version: Linux xie-PC 5.14.0-rc4-amd64-desktop #1 SMP Wed Aug 4 14:50:57 CST 2021 x86_64 GNU/Linux
run your reproduction code:
./issue
Nop completion received with user_data: 42 and res: 0
io_uring_wait_cqe_timeout 2: Timer expired
Final submit ret: 0 (return value is zero )
I don't expect this scenario to arise for Linux versions 5.11 and later because with IORING_ENTER_EXT_ARG set, liburing can pass a pointer to the timespec struct (with the timeout duration) directly into the io_uring_enter syscall to achieve a timeout. Before 5.11, to do the same thing, I believe liburing creates its own timeout operations and consumes the completion events, which can lead to this case.
Hello! We’re running liburing master (as of e98b974502d) on Linux 5.4.17 and are running into some odd and possibly unexpected behavior. We noticed while using io_uring_wait_cqe_timeout() that occasionally a later call to io_uring_submit() would return a count of submitted SQE’s one greater than the number we expected because we thought the return value should equal the number of SQE’s previously acquired with io_uring_get_sqe() that have not yet been submitted.
After looking deeper into the liburing code, it seems that this is happens when an expired timeout event from a timeout SQE created internally by liburing (with user_data == LIBURING_UDATA_TIMEOUT) gets handled in __io_uring_peek_cqe(), which ultimately causes the system call to io_uring_enter() to be skipped in _io_uring_get_cqe(), even when there are SQE’s that need to be submitted. This means that when calling io_uring_wait_cqe_timeout(), it is not guaranteed that the timeout SQE created by liburing will be properly submitted until the user makes a later call to io_uring_submit() when they would see the extra submission reflected in the return value.
Below is a short reproduction: