summaryrefslogtreecommitdiff
path: root/tests/functional
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2026-05-01 07:44:58 -0300
committerEuAndreh <eu@euandre.org>2026-05-01 07:44:58 -0300
commit4ea09f1e389fe410aa67faab866e67bc781214fa (patch)
treed7f51900de3f666019dfcda4076297a9411cdb34 /tests/functional
parentBump welcome-banner counts after RPL_005 split (diff)
downloadpapod-4ea09f1e389fe410aa67faab866e67bc781214fa.tar.gz
papod-4ea09f1e389fe410aa67faab866e67bc781214fa.tar.xz
Fix JOIN race: pin NAMES/broadcast to atomic membership snapshot
Two clients JOINing the same channel concurrently could each see the other in their own NAMES reply, and both could end up auto-opped on a freshly-created channel. The cause was that join-one! did: (swap! channels update handle (fnil conj #{}) nick) ... (get @channels handle) ;; for NAMES + broadcast + auto-op Between the swap! and the @channels read, a peer's swap! could land, so the read returned a set that already included them. Switch the swap to swap-vals!, capture members-before / members-after as a snapshot of state at the moment of our atomic update, and feed that snapshot to the broadcast loop, the metadata-2 push, the away- notify push, the auto-op decision, and the NAMES reply (via a new :members keyword on names-for). Auto-op now keys off (empty? members-before) instead of comparing the live atom to #{nick}. Surfaced and verified by the differential test in chat.papo.im, which previously had to insert quiesce checkpoints between concurrent JOINs to dodge the race; those checkpoints are no longer needed.
Diffstat (limited to 'tests/functional')
0 files changed, 0 insertions, 0 deletions