Skip to content

Remove stale WebSocket clients after async send failures#1803

Open
frickl wants to merge 3 commits into
bitaxeorg:masterfrom
frickl:fix-websocket-stale-client-cleanup-master
Open

Remove stale WebSocket clients after async send failures#1803
frickl wants to merge 3 commits into
bitaxeorg:masterfrom
frickl:fix-websocket-stale-client-cleanup-master

Conversation

@frickl

@frickl frickl commented Jul 5, 2026

Copy link
Copy Markdown

Summary

This change improves WebSocket connection handling by removing stale clients
when httpd_ws_send_frame_async() fails.

Additionally, websocket_broadcast() now copies the client list while holding
the mutex and performs the actual sends after releasing the mutex.

Problem

Under repeated WebSocket reconnects (built-in UI and external monitoring
clients), stale client entries could accumulate after failed async sends.

Over time this could exhaust MAX_WEBSOCKET_CLIENTS, resulting in:

  • 429 Too Many Requests
  • httpd_accept_conn: error in accept (113)
  • broken WebSocket connections
  • unavailable log and graph pages

Solution

  • remove stale WebSocket clients after async send failures
  • trigger HTTP session cleanup
  • broadcast outside the client mutex by first copying the client list

Broadcasting is performed after releasing the client mutex to avoid modifying
the client list while iterating over it during send failures.

Testing

Tested on a Bitaxe Gamma (Board 601, BM1370).

The miner was operated for several hours with both the built-in web UI and
additional external WebSocket monitoring clients.

After the change:

  • stale clients are removed correctly
  • no further exhaustion of MAX_WEBSOCKET_CLIENTS was observed
  • the web UI remained stable during testing

@WantClue

WantClue commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Thanks, this looks like the right direction. Copying the fd list before broadcasting fixes the mutex/reentrancy problem, and removing the client on httpd_ws_send_frame_async() failure should prevent stale entries from exhausting MAX_WEBSOCKET_CLIENTS.

One small issue before moving on: the new log lines index type_counts[type] even though the increment/decrement is guarded by type >= 0 && type < WS_TYPE_MAX. Could you guard the log value too, or validate type before adding the client?

Optional but useful: please log the return value from httpd_sess_trigger_close() if it fails, since that would help diagnose cases where the websocket registry was cleaned but the HTTP session was already gone.

Also, minor wording nit: httpd_ws_send_frame_async() is the ESP-IDF “send outside the request handler” API, not the callback-based async completion API. This PR handles immediate send failures, not later queued-send completion failures.

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