From c1373f0d61ef66021d3c9bb7277b140083c04e37 Mon Sep 17 00:00:00 2001 From: Petr Date: Tue, 30 Jun 2026 19:24:45 +0200 Subject: [PATCH] fix(gemini): bound cancel goroutine to Download lifetime --- internal/protocol/gemini/gemini.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/internal/protocol/gemini/gemini.go b/internal/protocol/gemini/gemini.go index 1a2d23a..6b6c604 100644 --- a/internal/protocol/gemini/gemini.go +++ b/internal/protocol/gemini/gemini.go @@ -100,10 +100,18 @@ func (p *Protocol) downloadWithRedirects(ctx context.Context, req *core.Download // Close the connection when the context is cancelled so any // blocking Read returns immediately instead of waiting for the - // 30-second deadline. + // 30-second deadline. The done channel bounds the goroutine to + // the lifetime of this call: when Download returns, defer + // close(done) lets the goroutine exit even if the parent context + // was never cancelled. + done := make(chan struct{}) + defer close(done) go func() { - <-ctx.Done() - conn.Close() + select { + case <-ctx.Done(): + conn.Close() + case <-done: + } }() // Send request: URL + CRLF