3383595296e0a666ec27f5038e8fb02775a8c70b
processCommand() read/mutated the `subscriptions` map and individual Subscription objects' `subscribers` vectors (via subscribe()/unsubscribe()/ event()/the "publish" branch's own insert()) without taking `lock` at all, even though add() and removeSessionSubscriptions() already do take it for the exact same state. removeSessionSubscriptions() runs from ~TCPSession(), on whatever thread happens to be tearing down a *different* connection, so one thread erasing a session from a Subscription's subscribers vector could run concurrently with another thread iterating (event()) or appending to (subscribe()) that same vector - a plain unsynchronized data race. Reproduced live while testing an unrelated ItemDataBase fix: rapid connect/ subscribe/disconnect cycles against the "createItem" subscription produced a real segfault, confirmed via gdb - Socket::write() -> resetSocket() dereferencing a corrupted EPoll reference, consistent with iterating a vector that another thread was concurrently erasing from. Wrapped the whole method body in a std::lock_guard on the same `lock` mutex SubscriptionManager already has. Verified no reentrancy risk: nothing reachable from processCommand() (including subscription handlers' own process()/onSubscribe() implementations) calls back into processCommand(), add(), or removeSessionSubscriptions() on the same thread, and `lock` is a plain non-recursive std::mutex, so this can't deadlock. Verified fix: the exact repro sequence that segfaulted the server twice now runs clean, server stays up. Not touched: Subscription::sendToAll() has no live callers (dead code); dynamically `new`'d *OWNER subscriptions are still never delete()'d when unpublished (a pre-existing leak, not a crash) - both out of scope here.
Description
This repository provides core functionality for TCP and UDP servers using the epoll linux function.
184 MiB
0 Stars
1 Watchers
0 Forks
Languages
C++
99.6%
Shell
0.4%