From 5f877afb9e4cc92a952490d115996ab84d46899f Mon Sep 17 00:00:00 2001 From: pptx704 Date: Wed, 15 Apr 2026 18:31:48 +0600 Subject: [PATCH] Remove PTY inactivity timeout to keep terminal sessions alive indefinitely Sessions now only end on process exit or explicit kill, not idle time. The keepalive ping every 30s remains to prevent network-level disconnects. --- internal/api/handlers_pty.go | 39 ------------------------------------ internal/api/openapi.yaml | 1 - 2 files changed, 40 deletions(-) diff --git a/internal/api/handlers_pty.go b/internal/api/handlers_pty.go index 6a906b1..cd5dcae 100644 --- a/internal/api/handlers_pty.go +++ b/internal/api/handlers_pty.go @@ -23,7 +23,6 @@ import ( ) const ( - ptyInactivityTimeout = 120 * time.Second ptyKeepaliveInterval = 30 * time.Second ptyDefaultCmd = "/bin/bash" ptyDefaultCols = 80 @@ -246,10 +245,6 @@ func runPtyLoop( ) { var wg sync.WaitGroup - // Inactivity timer — reset on input/resize, fires kill after timeout. - timer := time.NewTimer(ptyInactivityTimeout) - defer timer.Stop() - // Output pump: read from Connect stream, write to WebSocket. wg.Add(1) go func() { @@ -317,7 +312,6 @@ func runPtyLoop( })); err != nil { slog.Debug("pty send input error", "error", err) } - resetTimer(timer, ptyInactivityTimeout) case "resize": cols := msg.Cols @@ -331,7 +325,6 @@ func runPtyLoop( })); err != nil { slog.Debug("pty resize error", "error", err) } - resetTimer(timer, ptyInactivityTimeout) } case "kill": @@ -364,26 +357,6 @@ func runPtyLoop( } }() - // Inactivity timeout goroutine. - wg.Add(1) - go func() { - defer wg.Done() - select { - case <-timer.C: - slog.Info("pty session timed out", "sandbox_id", sandboxID, "tag", tag) - rpcCtx, rpcCancel := context.WithTimeout(context.Background(), 5*time.Second) - if _, err := agent.PtyKill(rpcCtx, connect.NewRequest(&pb.PtyKillRequest{ - SandboxId: sandboxID, - Tag: tag, - })); err != nil { - slog.Debug("pty timeout kill error", "error", err) - } - rpcCancel() - cancel() - case <-ctx.Done(): - } - }() - wg.Wait() } @@ -391,15 +364,3 @@ func runPtyLoop( func newPtyTag() string { return "pty-" + id.NewPtyTag() } - -// resetTimer safely resets a timer by stopping it and draining the channel -// before resetting, avoiding the race documented in time.Timer.Reset. -func resetTimer(t *time.Timer, d time.Duration) { - if !t.Stop() { - select { - case <-t.C: - default: - } - } - t.Reset(d) -} diff --git a/internal/api/openapi.yaml b/internal/api/openapi.yaml index 031cefd..984a37d 100644 --- a/internal/api/openapi.yaml +++ b/internal/api/openapi.yaml @@ -1386,7 +1386,6 @@ paths: PTY data (input and output) is base64-encoded because it contains raw terminal bytes (escape sequences, control codes) that are not valid UTF-8. - Sessions have a 120-second inactivity timeout (reset on input/resize). Sessions persist across WebSocket disconnections — the process keeps running in the capsule. Use the `tag` from the "started" response to reconnect later.