mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
io_uring/io-wq: no new workers once the exit has begun
io_wq_exit_start() sets IO_WQ_BIT_EXIT, but worker creation task_work queued before that stays queued until io_wq_exit_workers() cancels it. In between the task runs its task_work while canceling requests, and a worker can still get created. That's a problem for exec. begin_new_exec() calls io_uring_task_cancel() after de_thread(), when it's supposedly the only thread left, and io_wq_exit_workers() only waits for ->worker_done, which a worker completes before do_exit(). So the exiting worker is still in the thread group, using the mm, files and sighand, while exec replaces them. Easy to hit with a signal pending when create_io_thread() fails and the retry gets queued right before execve(). Cancel the queued creation task_work as soon as the exit bit is set. Pending work that isn't otherwise canceled now ends with -ECANCELED when the io-wq is destroyed, rather than depending on whether the task happened to run its task_work first. Fixes:685fe7feed("io-wq: eliminate the need for a manager thread") Signed-off-by: Josef Bacik <josef@toxicpanda.com> [axboe: the barrier is already upstream, see0e5663856b, only the cancel is new] Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
2295613cd3
commit
47c68f9250
|
|
@ -1420,6 +1420,12 @@ void io_wq_exit_start(struct io_wq *wq)
|
|||
set_bit(IO_WQ_BIT_EXIT, &wq->state);
|
||||
/* Pairs with task_work_add() in io_queue_worker_create(). */
|
||||
smp_mb__after_atomic();
|
||||
/*
|
||||
* No more workers from here on. The caller is going to run its task
|
||||
* work, and on exec a thread that is created now would still be
|
||||
* around, exiting, by the time that the caller must be on its own.
|
||||
*/
|
||||
io_wq_cancel_tw_create(wq);
|
||||
}
|
||||
|
||||
static void io_wq_cancel_tw_create(struct io_wq *wq)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user