[PATCH] 9p: don't ignore fatal signals during flush

Shigeru Yoshida <[email protected]>
Newsgroups dev.linux.lists.v9fs,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
When a 9P RPC request is interrupted by a signal, p9_client_rpc() clears
TIF_SIGPENDING and attempts to flush the pending request by calling
p9_client_flush(). Since commit 9523feac272c switched the wait from
wait_event_interruptible() to wait_event_killable(), only SIGKILL can
interrupt the wait. However, the flush path also clears TIF_SIGPENDING,
which prevents subsequent wait_event_killable() calls from detecting the
already-pending SIGKILL. This makes the task unkillable.

When a coredump is initiated by another thread, zap_process() sends
SIGKILL to all threads. If a thread is stuck in the flush path as
described above, it never exits, and the dumper thread waits forever in
coredump_wait(), resulting in a hung task.

The same issue exists in p9_client_zc_rpc().

Skip the flush and the P9_TFLUSH retry loop when a fatal signal is
pending so that the task can exit promptly.

Fixes: 9523feac272c ("net/9p: Switch to wait_event_killable()")
Reported-by: [email protected]
Signed-off-by: Shigeru Yoshida <[email protected]>
---
 net/9p/client.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/net/9p/client.c b/net/9p/client.c
index f0dcf252af7e..28742f19041e 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -599,7 +599,7 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
 	smp_rmb();
 
 	if (err == -ERESTARTSYS && c->status == Connected &&
-	    type == P9_TFLUSH) {
+	    type == P9_TFLUSH && !fatal_signal_pending(current)) {
 		sigpending = 1;
 		clear_thread_flag(TIF_SIGPENDING);
 		goto again;
@@ -609,7 +609,8 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
 		p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
 		err = req->t_err;
 	}
-	if (err == -ERESTARTSYS && c->status == Connected) {
+	if (err == -ERESTARTSYS && c->status == Connected &&
+	    !fatal_signal_pending(current)) {
 		p9_debug(P9_DEBUG_MUX, "flushing\n");
 		sigpending = 1;
 		clear_thread_flag(TIF_SIGPENDING);
@@ -694,7 +695,8 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type,
 		p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
 		err = req->t_err;
 	}
-	if (err == -ERESTARTSYS && c->status == Connected) {
+	if (err == -ERESTARTSYS && c->status == Connected &&
+	    !fatal_signal_pending(current)) {
 		p9_debug(P9_DEBUG_MUX, "flushing\n");
 		sigpending = 1;
 		clear_thread_flag(TIF_SIGPENDING);
-- 
2.52.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.