WebSocket handler context is self-referential, causing an unrecoverable stack overflow
What
App.WebSocket's handler builds the context it hands to a handler like this:
ctx.Context = context.WithValue(ctx, websocket.WSConnectionKey, conn)ctx is *gofr.Context, which embeds context.Context. Passing ctx itself (not ctx.Context) as the parent to context.WithValue makes the resulting value-context self-referential: its parent is ctx, and ctx.Context is the very context being constructed.
Impact
Any call that walks the parent chain on this context, such as .Done() or a .Value() lookup for a key other than websocket.WSConnectionKey, recurses into itself forever:
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflowA stack overflow is a fatal error, not a panic, so recover() cannot catch it and the whole process dies. A WebSocket handler that reads any context value other than the WS key (tracing, auth, or any SDK taking a context.Context) hits this.
It currently goes unnoticed because Container.GetConnectionFromContext looks up exactly the one key that returns before recursing.
Where
pkg/gofr/websocket.go, in App.WebSocket's registered handler:
ctx.Context = context.WithValue(ctx, websocket.WSConnectionKey, conn)Suggested fix
Use the embedded context as the parent, not ctx itself:
ctx.Context = context.WithValue(ctx.Context, websocket.WSConnectionKey, conn)Notes
- Independent of the data race fixed in #4111 (
serveWithGoroutinereadingc.Contextconcurrently with this same line reassigning it). That fix stops the parent goroutine from ever calling.Done()on the poisoned context, which closes one crash path, but leaves the self-reference inc.Contextitself for the handler and anything downstream of it. - Surfaced during review of #4111.
Source: gofr-dev/gofr