diff --git a/engine/access/rest/websockets/controller.go b/engine/access/rest/websockets/controller.go index be39606ba44..a1739f204b3 100644 --- a/engine/access/rest/websockets/controller.go +++ b/engine/access/rest/websockets/controller.go @@ -220,6 +220,13 @@ func (c *Controller) configureKeepalive() error { // keepalive sends a ping message periodically to keep the WebSocket connection alive // and avoid timeouts. func (c *Controller) keepalive(ctx context.Context) error { + defer func() { + // gracefully handle panics from github.com/gorilla/websocket + if r := recover(); r != nil { + c.logger.Warn().Interface("recovered_context", r).Msg("keepalive routine recovered from panic") + } + }() + pingTicker := time.NewTicker(PingPeriod) defer pingTicker.Stop() @@ -246,10 +253,12 @@ func (c *Controller) keepalive(ctx context.Context) error { // If no messages are sent within InactivityTimeout and no active data providers exist, // the connection will be closed. func (c *Controller) writeMessages(ctx context.Context) error { - inactivityTicker := time.NewTicker(c.inactivityTickerPeriod()) - defer inactivityTicker.Stop() - - lastMessageSentAt := time.Now() + defer func() { + // gracefully handle panics from github.com/gorilla/websocket + if r := recover(); r != nil { + c.logger.Warn().Interface("recovered_context", r).Msg("writer routine recovered from panic") + } + }() defer func() { // drain the channel as some providers may still send data to it after this routine shutdowns @@ -260,6 +269,11 @@ func (c *Controller) writeMessages(ctx context.Context) error { }() }() + inactivityTicker := time.NewTicker(c.inactivityTickerPeriod()) + defer inactivityTicker.Stop() + + lastMessageSentAt := time.Now() + for { select { case <-ctx.Done(): @@ -308,6 +322,13 @@ func (c *Controller) inactivityTickerPeriod() time.Duration { // readMessages continuously reads messages from a client WebSocket connection, // validates each message, and processes it based on the message type. func (c *Controller) readMessages(ctx context.Context) error { + defer func() { + // gracefully handle panics from github.com/gorilla/websocket + if r := recover(); r != nil { + c.logger.Warn().Interface("recovered_context", r).Msg("reader routine recovered from panic") + } + }() + for { var message json.RawMessage if err := c.conn.ReadJSON(&message); err != nil {