Skip to content

Fix goroutine leaks in proxy testing code - #227

Merged
jadolg merged 2 commits into
mainfrom
claude/goleak-integration-testing-qfojn0
Jul 16, 2026
Merged

Fix goroutine leaks in proxy testing code#227
jadolg merged 2 commits into
mainfrom
claude/goleak-integration-testing-qfojn0

Conversation

@jadolg

@jadolg jadolg commented Jul 16, 2026

Copy link
Copy Markdown
Member

Summary

This PR fixes goroutine leaks in the shadowsocks proxy testing code by properly managing the lifecycle of goroutines started during proxy operations. The changes ensure that goroutines are cancelled when requests timeout or are cancelled, and HTTP connections are properly cleaned up.

Key Changes

  • Added goleak verification: Integrated go.uber.org/goleak test harness in both root and ssproxy packages to detect goroutine leaks during testing
  • Fixed ListenForOneConnection goroutine leak: Modified ListenForOneConnection to accept a context.Context parameter that bounds the upstream server dial operation, ensuring the goroutine terminates when the context is cancelled
  • Fixed HTTP connection leaks: Updated IsIPInfoOffline to explicitly disable HTTP keep-alives and defer closing idle connections on the transport, preventing connection pooling from holding resources
  • Updated function signature: Changed ListenForOneConnection to require a context as the first parameter and updated the call site in GetShadowsocksProxyDetails to pass a cancellable context

Implementation Details

  • The context passed to ListenForOneConnection is created with context.WithCancel() and deferred cancelled in GetShadowsocksProxyDetails, ensuring cleanup after the proxy test completes
  • The upstream dial now uses net.Dialer.DialContext() instead of net.Dial() to respect the provided context's cancellation
  • HTTP transport configuration explicitly disables keep-alives to prevent idle connections from persisting beyond the test scope

https://claude.ai/code/session_01VPGSpvYdaeVxKXXkoJERsH

claude added 2 commits July 16, 2026 14:07
Run the ssproxy and main package test suites under go.uber.org/goleak
via TestMain, guarding the actual proxy-testing code paths (the SOCKS
listener and relay goroutines) against goroutine leaks.

goleak surfaced two real leaks that are also fixed here:

- IsIPInfoOffline used the default HTTP transport, leaking a persistent
  connection's readLoop goroutine into the pool. It now uses a dedicated
  transport with keep-alives disabled and closes idle connections.

- ListenForOneConnection dialed the upstream server with an unbounded
  net.Dial, so the goroutine outlived a cancelled/timed-out request. It
  now takes a context and dials with DialContext; GetShadowsocksProxyDetails
  cancels that context on return.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VPGSpvYdaeVxKXXkoJERsH
Name the files after what they contain (goleak setup) rather than the
generic main_test.go.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VPGSpvYdaeVxKXXkoJERsH
@jadolg
jadolg merged commit 8a78fa1 into main Jul 16, 2026
7 checks passed
@jadolg
jadolg deleted the claude/goleak-integration-testing-qfojn0 branch July 16, 2026 14:21
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.

2 participants