Skip to content

Allow waiting for all goroutines to exit on client connection close #8655

@twz123

Description

@twz123

Use case(s) - what problem will this feature solve?

When a client connection closes, the goroutines associated with that connection are cancelled. However, Close() returns before all of those goroutines have actually exited.

This usually isn't a problem in long-lived applications, but in short-lived clients, tests, or graceful shutdown paths, the asynchronous cleanup can cause issues. Those goroutines may still perform observable side effects after Close() returns, making it impossible to know when all background work has finished. This leads to unpredictable behavior in situations where deterministic teardown matters.

A common example is shutting down the logging subsystem: background tasks may still emit log messages after Close() returns, racing with the logging shutdown. Similarly, test scenarios that verify proper resource cleanup can become unreliable.

Providing a way to wait until all internal goroutines have exited would make shutdowns more predictable and simplify synchronization in these cases.

Proposed Solution

Provide a mechanism that blocks until all goroutines spawned by a connection have completed their cleanup and exited. I'm not proposing a specific API - whatever fits best.

Internally, this could be implemented by using a sync.WaitGroup or a similar mechanism to track active goroutines that aren't already tracked elsewhere. For backward compatibility, the existing Close() method should remain "non-blocking".

I've also considered making this behavior unconditional for Close(). Although this would be the most intuitive approach for me, it's probably not feasible because it would affect the shutdown timing and blocking behavior of many applications that rely on the current behavior?

Alternatives Considered

Live with the current situation and build workarounds to mitigate this in scenarios where it's required. However, none of those workarounds will be bullet-proof. Things like log statements about connections that have already been closed can't be worked around.

Additional Context

I've identified three goroutines which will currently outlive the call to Close() so far:

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions