fix: send socket events only from loop()

Every socket event is formatted into one static buffer by one shared
formatter.  setConnected() runs on the WiFi/Ethernet event task and sent
memStatus, wifiStrength and ethernet, then ran sockEmit.loop(), while
loop() could be building its own event.  _safecat() checks the room and
then writes at _len, so another task moving _len in between could write
past the end of g_response.

setConnected() now sends nothing.  loop() broadcasts the status every
STATUS_EMIT_MS (30 s): memStatus, then ethernet, or wifiStrength when it
moved 3 dBm or changed channel.  A client that connects still gets all
of it at once from initClients(), so needsBroadcast and the 1.5 s tick
go, and so does the 1.5 s memStatus for the config panel.

SocketEmitter records loop()'s task in begin().  Off it, beginEmit()
logs and hands out a formatter that writes nothing, and endEmit(),
endEmitRoom() and loop() do nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cjkas 2026-10-21 15:27:21 +02:00
parent 474c7c0f42
commit 25d548ef07
11 changed files with 153 additions and 117 deletions

View file

@ -22,6 +22,11 @@ class SocketEmitter {
protected:
uint8_t newclients = 0;
uint8_t newClients[5] = {255,255,255,255,255};
// loop()'s task, recorded by begin(). Only it may send; see emitAllowed().
TaskHandle_t _owner = nullptr;
// What beginEmit() hands any other task, so the event goes nowhere.
JsonSockEvent _discard;
bool onLoopTask() const;
void delayInit(uint8_t num);
public:
JsonSockEvent json;