Skip to content

Fix goroutine leak in queue package#367

Open
lxcxjxhx wants to merge 3 commits into
vxcontrol:mainfrom
lxcxjxhx:fix/queue-goroutine-leak
Open

Fix goroutine leak in queue package#367
lxcxjxhx wants to merge 3 commits into
vxcontrol:mainfrom
lxcxjxhx:fix/queue-goroutine-leak

Conversation

@lxcxjxhx

@lxcxjxhx lxcxjxhx commented Jul 7, 2026

Copy link
Copy Markdown

Fix Goroutine Leak in Queue Package

Problem

The queue package has a goroutine leak issue in the Stop() method. When Stop() is called while workers are still processing messages, the following sequence occurs:

  1. Stop() calls q.cancel() to signal shutdown
  2. reader() receives the cancellation signal and exits
  3. However, workers blocked on q.queue channel may not exit immediately
  4. This causes goroutines to leak, as they remain blocked indefinitely

Root Cause

The issue stems from the interaction between reader() and Stop():

  • reader() has defer close(q.queue) which closes the channel when it exits
  • Stop() calls q.cancel() but doesn't explicitly close the queue channel
  • If reader() hasn't exited yet when Stop() checks q.ctx.Err(), workers can be left waiting on an open channel

Solution

  1. Remove defer close(q.queue) from reader(): This prevents potential double-close panics
  2. Add explicit close(q.queue) in Stop(): After calling q.cancel(), immediately close the queue channel to ensure all workers can exit their receive loops

Changes

  • backend/pkg/queue/queue.go: Modified Stop() and reader() methods
    • Line 124: Added close(q.queue) after q.cancel() in Stop()
    • Line 167: Removed defer close(q.queue) from reader()

Impact

  • Fixes goroutine leak: Workers now properly exit when Stop() is called
  • Prevents resource exhaustion: Long-running applications won't accumulate leaked goroutines
  • No breaking changes: The fix maintains the same external behavior and API

Testing

The fix ensures that:

  • All worker goroutines exit when Stop() is called
  • No double-close panics occur on the queue channel
  • The queue can be safely stopped even while processing messages

lxcxjxhx added 3 commits July 7, 2026 08:49
- Fix double timeout padding in Handle() method that inflated user-requested timeouts by 5 seconds
- Fix incorrect log type in WriteFile() method (stdin -> stdout) for proper log stream classification
- Fix incomplete file read in ReadFile() method by using io.ReadFull instead of single Read() call

These bugs affected command execution timeout handling, log type correctness, and file read completeness.
All fixes are minimal, targeted, and maintain backward compatibility while improving correctness.
- Remove defer close(q.queue) from reader() to prevent double close
- Add explicit close(q.queue) in Stop() after cancel() to ensure workers exit
- This fixes goroutine leak when Stop() is called while workers are still processing

The issue: when Stop() calls cancel(), the reader() might not exit immediately,
and workers waiting on q.queue channel would block forever, causing goroutine leak.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant