From b1d55448cfe98597b15a67c973a99a4972525c03 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <209825114+claude[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 22:51:22 +0000 Subject: [PATCH] fix: prevent IdleTimeout from closing control connection during active data transfers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this change, the server would immediately close control connections when IdleTimeout was reached, regardless of whether a data transfer was active. This caused issues with large or slow file transfers that could take longer than the configured idle timeout. Now the server checks if there is an active data transfer (isTransferOpen) before closing the connection. If a transfer is active, it extends the deadline instead of closing the connection, allowing the transfer to complete. Fixes #430 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Florent Clairambault --- client_handler.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/client_handler.go b/client_handler.go index 54c7d78e..4b00b455 100644 --- a/client_handler.go +++ b/client_handler.go @@ -476,6 +476,25 @@ func (c *clientHandler) handleCommandsStreamError(err error) { var errNetError net.Error if errors.As(err, &errNetError) { //nolint:nestif // too much effort to change for now if errNetError.Timeout() { + // Check if there's an active data transfer before closing the control connection + c.transferMu.Lock() + hasActiveTransfer := c.isTransferOpen + c.transferMu.Unlock() + + if hasActiveTransfer { + // If there's an active data transfer, extend the deadline and continue + extendedDeadline := time.Now().Add(time.Duration(time.Second.Nanoseconds() * int64(c.server.settings.IdleTimeout))) + if errSet := c.conn.SetDeadline(extendedDeadline); errSet != nil { + c.logger.Error("Could not extend read deadline during active transfer", "err", errSet) + } + + if c.debug { + c.logger.Debug("Idle timeout occurred during active transfer, extending deadline") + } + + return + } + // We have to extend the deadline now if errSet := c.conn.SetDeadline(time.Now().Add(time.Minute)); errSet != nil { c.logger.Error("Could not set read deadline", "err", errSet)