[PR #139] [CLOSED] fix: prevent goroutine leak in terminal exec timeout handling #185

Closed
opened 2026-06-06 22:09:36 -04:00 by yindo · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/vxcontrol/pentagi/pull/139
Author: @haosenwang1018
Created: 2/23/2026
Status: Closed

Base: masterHead: fix/goroutine-leak-exec-timeout


📝 Commits (1)

  • c12c0b1 fix: prevent goroutine leak in terminal exec timeout handling

📊 Changes

1 file changed (+5 additions, -2 deletions)

View changed files

📝 backend/pkg/tools/terminal.go (+5 -2)

📄 Description

Problem

When getExecResult times out via ctx.Done(), the function returns but leaves a goroutine blocked on io.Copy(&dst, resp.Reader). The connection (resp) is only closed by defer after the function returns, but by that point the goroutine is already leaked — io.Copy may remain blocked even after resp.Close() because the close races with the blocked read.

Each timed-out command leaks one goroutine and its associated resources (#108).

Fix

  • Close resp before waiting for the goroutine on timeout, which unblocks io.Copy
  • Wait for the goroutine (<-done) after closing to ensure clean shutdown
  • On the normal path, close resp immediately after copy completes
  • Remove defer resp.Close() since both paths now close explicitly

Before

timeout → return → defer resp.Close() → goroutine still blocked on io.Copy

After

timeout → resp.Close() → io.Copy returns → <-done → return (no leak)

Fixes #108


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/vxcontrol/pentagi/pull/139 **Author:** [@haosenwang1018](https://github.com/haosenwang1018) **Created:** 2/23/2026 **Status:** ❌ Closed **Base:** `master` ← **Head:** `fix/goroutine-leak-exec-timeout` --- ### 📝 Commits (1) - [`c12c0b1`](https://github.com/vxcontrol/pentagi/commit/c12c0b1d5829e0bed79f983d4d3408a4885d8843) fix: prevent goroutine leak in terminal exec timeout handling ### 📊 Changes **1 file changed** (+5 additions, -2 deletions) <details> <summary>View changed files</summary> 📝 `backend/pkg/tools/terminal.go` (+5 -2) </details> ### 📄 Description ## Problem When `getExecResult` times out via `ctx.Done()`, the function returns but leaves a goroutine blocked on `io.Copy(&dst, resp.Reader)`. The connection (`resp`) is only closed by `defer` after the function returns, but by that point the goroutine is already leaked — `io.Copy` may remain blocked even after `resp.Close()` because the close races with the blocked read. Each timed-out command leaks one goroutine and its associated resources (#108). ## Fix - Close `resp` **before** waiting for the goroutine on timeout, which unblocks `io.Copy` - Wait for the goroutine (`<-done`) after closing to ensure clean shutdown - On the normal path, close `resp` immediately after copy completes - Remove `defer resp.Close()` since both paths now close explicitly ## Before ``` timeout → return → defer resp.Close() → goroutine still blocked on io.Copy ``` ## After ``` timeout → resp.Close() → io.Copy returns → <-done → return (no leak) ``` Fixes #108 --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
yindo added the pull-request label 2026-06-06 22:09:36 -04:00
yindo closed this issue 2026-06-06 22:09:36 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vxcontrol/pentagi#185