> [...] > > diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c > index 75f0087183e5..56097627eafc 100644 > --- a/io_uring/io_uring.c > +++ b/io_uring/io_uring.c > @@ -2472,7 +2472,7 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx, > return 1; > if (unlikely(!llist_empty(&ctx->work_llist))) > return 1; > - if (unlikely(test_thread_flag(TIF_NOTIFY_SIGNAL))) > + if (unlikely(task_work_pending(current))) > return 1; > if (unlikely(task_sigpending(current))) > return -EINTR; > diff --git a/io_uring/io_uring.h b/io_uring/io_uring.h > index 9d70b2cf7b1e..2fbf0ea9c171 100644 > --- a/io_uring/io_uring.h > +++ b/io_uring/io_uring.h > @@ -308,15 +308,17 @@ static inline int io_run_task_work(void) > */ > if (test_thread_flag(TIF_NOTIFY_SIGNAL)) > clear_notify_signal(); > + > + if (test_thread_flag(TIF_NOTIFY_RESUME)) { > + __set_current_state(TASK_RUNNING); > + resume_user_mode_work(NULL); > + } > + > /* > * PF_IO_WORKER never returns to userspace, so check here if we have > * notify work that needs processing. > */ > if (current->flags & PF_IO_WORKER) { > - if (test_thread_flag(TIF_NOTIFY_RESUME)) { > - __set_current_state(TASK_RUNNING); > - resume_user_mode_work(NULL); > - } > if (current->io_uring) { > unsigned int count = 0; > > Can confirm that also this patch fixes the issue on my end (both with the reordering of the task_work and without it). Also found a different way to trigger the issue that does not misuse IOSQE_IO_LINK. Do three sends with IOSQE_CQE_SKIP_SUCCESS | IOSQE_IO_LINK followed by a close with IOSQE_CQE_SKIP_SUCCESS on a ring with IORING_SETUP_DEFER_TASKRUN. I confirmed that that test case also first brakes on 846072f16eed3b3fb4e59b677f3ed8afb8509b89 and is fixed by either of the two patches you sent. Not sure if that's a preferable test case compared to the weirder ealier one. You can find it below as a patch to the existing test case in the liburing repo: diff --git a/test/linked-defer-close.c b/test/linked-defer-close.c index 4be96b3..f9ef6eb 100644 --- a/test/linked-defer-close.c +++ b/test/linked-defer-close.c @@ -88,6 +88,7 @@ int main(int argc, char *argv[]) struct sockaddr_in saddr; char *msg1 = "message number 1\n"; char *msg2 = "message number 2\n"; + char *msg3 = "message number 3\n"; int val, send_fd, ret, sockfd; struct sigaction act[2] = { }; struct thread_data td; @@ -182,17 +183,22 @@ int main(int argc, char *argv[]) sqe = io_uring_get_sqe(&ring); io_uring_prep_send(sqe, send_fd, msg1, strlen(msg1), 0); sqe->user_data = IS_SEND; - sqe->flags = IOSQE_CQE_SKIP_SUCCESS; + sqe->flags = IOSQE_CQE_SKIP_SUCCESS | IOSQE_IO_LINK; sqe = io_uring_get_sqe(&ring); io_uring_prep_send(sqe, send_fd, msg2, strlen(msg2), 0); sqe->user_data = IS_SEND2; sqe->flags = IOSQE_CQE_SKIP_SUCCESS | IOSQE_IO_LINK; + sqe = io_uring_get_sqe(&ring); + io_uring_prep_send(sqe, send_fd, msg3, strlen(msg3), 0); + sqe->user_data = IS_SEND2; + sqe->flags = IOSQE_CQE_SKIP_SUCCESS | IOSQE_IO_LINK; + sqe = io_uring_get_sqe(&ring); io_uring_prep_close(sqe, send_fd); sqe->user_data = IS_CLOSE; - sqe->flags = IOSQE_CQE_SKIP_SUCCESS | IOSQE_IO_LINK; + sqe->flags = IOSQE_CQE_SKIP_SUCCESS; break; case IS_SEND: case IS_SEND2: