While the peer does not drain its receive buffer, every forwarded packet
would re-stall the reader thread for up to writeTimeout(), so a queued
Disconnect frame could wait behind the whole backlog. Remember a stalled
target (send slower than 2 s) and drop data for a short cooldown instead
of stalling; keep dispatcher writes bounded at 3 s. Control frames
(Connected/Disconnected) are unaffected.
The dataReadedServer lambda looked up the sub-client under
mutex_clients but called sendData() after the unlock; the client could
be deleted by the drainer in between (same UAF pattern that was fixed
in PICloudServer::_readed). Keep the send inside the locked section:
sendData only takes mutex_send/prog_s_mutex downstream, so the lock
hold is bounded.
stop() iterated clients while addClient()/removeClient() modified it
from other threads (reallocated vector iterators, data race). Copy the
list under mutex_clients and close the copy.
last_ping (PITimeMeasurer) was reset from the read thread
(dataReadedServer/pingReceived) without any lock while cleanClients
read it via lastPing() in the timer thread. Reset and read it under
mutex_clients (lock order map_mutex -> mutex_clients, consistent with
the registerClient path).