From 4dd16cb8408b7164cc204599e449f274cbc8ebe7 Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Sun, 19 Apr 2026 17:00:32 +0200 Subject: [PATCH] 9p: add 5s timeout to *wait reads for FUSE signal delivery FUSE puts blocked processes in D state (uninterruptible sleep) waiting for the read to return. SIGINT cannot interrupt D-state, so Ctrl+C has no effect even after Tflush cancels the goroutine. A 5s timeout causes the read to return periodically, letting FUSE unblock the client process and deliver any pending signals. Co-Authored-By: Claude Sonnet 4.6 --- internal/p9/server.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/p9/server.go b/internal/p9/server.go index 3f4604a..49a40cc 100644 --- a/internal/p9/server.go +++ b/internal/p9/server.go @@ -792,7 +792,12 @@ func (s *Server) read(cs *connState, fc *plan9.Fcall, ctx context.Context) *plan base = f.waitBase } cs.mu.RUnlock() - content, err := store.Wait(ctx, parts[2], base) + // Wrap with a short timeout so the FUSE read returns + // periodically, allowing pending signals (e.g. SIGINT) to + // be delivered to the blocked client process. + waitCtx, waitCancel := context.WithTimeout(ctx, 5*time.Second) + defer waitCancel() + content, err := store.Wait(waitCtx, parts[2], base) if err != nil { return errFcall(fc, err.Error()) }