summaryrefslogtreecommitdiff
path: root/yhttpd/src
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-06-30 13:30:28 +0300
committerPaul Buetow <paul@buetow.org>2026-06-30 13:30:28 +0300
commit4f8e26db8f645e8d50a9a9b31e5935c6967de55d (patch)
treec6985cc28c9a59e2ecc4f6b37850f1cc0b82f60f /yhttpd/src
parenta0a881fb8ddd48a51292af1af85708b4c3593804 (diff)
Implement the timer/garbage-collector (was disabled/unfinished)
wrap.cpp had '//TIMR->run(); // TODO' but timr::run() was never defined (wouldn't compile if uncommented), and the intended timer thread (timr::start) ran in a pthread and would race with the single-threaded libevent main loop (no locking on the shared room/user maps). Net effect: idle timeouts never ran, ghost users lingered in the online list forever after disconnect, and message timestamps were always 00:00:00 (s_time was only updated by the never-run timer). Also, even single-threaded, check_timeout was unsafe: user::set_online(false) does p_room->del_elem during hashmap::run_func's live begin/end iteration -> iterator invalidation/crash. Fix: - hashmap::run_func (both overloads): snapshot the values into a vector before invoking the callback, so callbacks may safely delete from the map during iteration. - timr::tick(): single-threaded 1s-cadence tick (called from the libevent main loop) that updates s_time/s_uptime every tick, and at the top of each minute runs check_timeout (idle timeout + auto-away), posts a PING keepalive to all streams, every 10 min cleans the ip cache, hourly runs garbage collection. - main.cpp: register a periodic libevent timer (1s, EV_PERSIST) calling timr::tick() in the event loop - no new thread. B1 use-after-free (found by independent review, fixed): when an idle user is reaped it moves to garbage while its long-lived stream context is still alive; the hourly remove_garbage would delete the user, leaving the context's p_user dangling (UAF on later disconnect). Fixed by: - gcol::remove_garbage now keeps garbage users whose stream is still open (get_stream_fd() >= 0) until the stream closes, deleting only closed-stream users (collected via a new collect_users_ helper since the hash_map base is privately inherited and not directly iterable). - handle_stream_read now reaps the disconnecting user from its room (set_online(false), a no-op if already idle-reaped) so a clean disconnect immediately clears the online list instead of lingering until idle-reap. Also removed the debug 'cout << SETTING OFFLINE' spam in set_online. Verified: timestamps now real (e.g. 10:29:20 vs old 00:00:00); idle users reaped at the next top-of-minute tick (no crash); clean disconnect removes the user from the online list; idle-reaped-then-stream-closed does not UAF (0 restarts); normal multi-user chat still works. Two independent fresh-context reviews: APPROVE-WITH-NITS; the B1 UAF and disconnect-reap findings were addressed; the pre-existing flush_stream hard-error UAF edge was filed as a separate follow-up.
Diffstat (limited to 'yhttpd/src')
0 files changed, 0 insertions, 0 deletions