Commit dbe1bdbb authored by Jens Axboe's avatar Jens Axboe

io_uring: handle signals for IO threads like a normal thread

We go through various hoops to disallow signals for the IO threads, but
there's really no reason why we cannot just allow them. The IO threads
never return to userspace like a normal thread, and hence don't go through
normal signal processing. Instead, just check for a pending signal as part
of the work loop, and call get_signal() to handle it for us if anything
is pending.

With that, we can support receiving signals, including special ones like
SIGSTOP.
Acked-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 10442994
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include <linux/rculist_nulls.h> #include <linux/rculist_nulls.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/tracehook.h> #include <linux/tracehook.h>
#include <linux/freezer.h>
#include "../kernel/sched/sched.h" #include "../kernel/sched/sched.h"
#include "io-wq.h" #include "io-wq.h"
...@@ -503,10 +502,15 @@ static int io_wqe_worker(void *data) ...@@ -503,10 +502,15 @@ static int io_wqe_worker(void *data)
if (io_flush_signals()) if (io_flush_signals())
continue; continue;
ret = schedule_timeout(WORKER_IDLE_TIMEOUT); ret = schedule_timeout(WORKER_IDLE_TIMEOUT);
if (try_to_freeze() || ret) if (signal_pending(current)) {
struct ksignal ksig;
if (!get_signal(&ksig))
continue; continue;
if (fatal_signal_pending(current))
break; break;
}
if (ret)
continue;
/* timed out, exit unless we're the fixed worker */ /* timed out, exit unless we're the fixed worker */
if (test_bit(IO_WQ_BIT_EXIT, &wq->state) || if (test_bit(IO_WQ_BIT_EXIT, &wq->state) ||
!(worker->flags & IO_WORKER_F_FIXED)) !(worker->flags & IO_WORKER_F_FIXED))
...@@ -714,9 +718,13 @@ static int io_wq_manager(void *data) ...@@ -714,9 +718,13 @@ static int io_wq_manager(void *data)
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
io_wq_check_workers(wq); io_wq_check_workers(wq);
schedule_timeout(HZ); schedule_timeout(HZ);
try_to_freeze(); if (signal_pending(current)) {
if (fatal_signal_pending(current)) struct ksignal ksig;
if (!get_signal(&ksig))
continue;
set_bit(IO_WQ_BIT_EXIT, &wq->state); set_bit(IO_WQ_BIT_EXIT, &wq->state);
}
} while (!test_bit(IO_WQ_BIT_EXIT, &wq->state)); } while (!test_bit(IO_WQ_BIT_EXIT, &wq->state));
io_wq_check_workers(wq); io_wq_check_workers(wq);
......
...@@ -78,7 +78,6 @@ ...@@ -78,7 +78,6 @@
#include <linux/task_work.h> #include <linux/task_work.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/io_uring.h> #include <linux/io_uring.h>
#include <linux/freezer.h>
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include <trace/events/io_uring.h> #include <trace/events/io_uring.h>
...@@ -6765,8 +6764,13 @@ static int io_sq_thread(void *data) ...@@ -6765,8 +6764,13 @@ static int io_sq_thread(void *data)
timeout = jiffies + sqd->sq_thread_idle; timeout = jiffies + sqd->sq_thread_idle;
continue; continue;
} }
if (fatal_signal_pending(current)) if (signal_pending(current)) {
struct ksignal ksig;
if (!get_signal(&ksig))
continue;
break; break;
}
sqt_spin = false; sqt_spin = false;
cap_entries = !list_is_singular(&sqd->ctx_list); cap_entries = !list_is_singular(&sqd->ctx_list);
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) { list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) {
...@@ -6809,7 +6813,6 @@ static int io_sq_thread(void *data) ...@@ -6809,7 +6813,6 @@ static int io_sq_thread(void *data)
mutex_unlock(&sqd->lock); mutex_unlock(&sqd->lock);
schedule(); schedule();
try_to_freeze();
mutex_lock(&sqd->lock); mutex_lock(&sqd->lock);
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) list_for_each_entry(ctx, &sqd->ctx_list, sqd_list)
io_ring_clear_wakeup_flag(ctx); io_ring_clear_wakeup_flag(ctx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment