MP: console-death freeze NOT REPRODUCIBLE + fix the latent game-listener-close bug (task #50)

Investigated the "console death froze peer replication" open question (2026-07-14)
with a direct 2-node repro (BT_REPL_LOG on a circling peer, affinity-pinned):

- Clean relay kill -> replicant kept circling smoothly through the kill, NO
  disconnect logged, node survived. Replication did NOT freeze.
- Deliberately STUCK console (scratchpad/btconsole_stuck.py: connect, start
  mission, then stop recv() while holding the socket OPEN = the exact
  "receive pad full -> close never seen" mode hypothesized) -> replicant kept
  moving the whole run. Replication did NOT freeze.

Conclusion: peer replication is INDEPENDENT of the console (pods replicate
peer-to-peer over the GAME socket; the console is a separate egg/mission/status
channel). The original freeze was a transient -- plausibly the same single-box
packet-jitter/CPU-contention artifact root-caused in 49d73dc -- or was fixed by
later MP work.

FIX (the one real bug found): L4NetworkManager::HostDisconnectedMessageHandler's
ConsoleHostType branch closed gameListenerSocket (the GAME listener) on a CONSOLE
disconnect -- a naming bug (the comment + commented-out OpenConnection intended a
CONSOLE re-listen, which CreateConsoleHost already does). Removed. Harmless to
established peer sockets (why a live match survives console loss) but it would
have blocked a NEW peer from joining after a console cycle. Verified: 2-node
still connects (All connections completed!) + the peer circles.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-15 15:52:35 -05:00
co-authored by Claude Opus 4.8
parent d1ce99402f
commit bc4d6e5597
3 changed files with 122 additions and 16 deletions
+9 -3
View File
@@ -966,9 +966,15 @@ void L4NetworkManager::HostDisconnectedMessageHandler(HostDisconnectedMessage* H
//
// Post a listen for a console so it can reconnect if it wants to.
//
shutdown(gameListenerSocket, SD_BOTH);
closesocket(gameListenerSocket);
gameListenerSocket = NULL;
// FIX (task #50, 2026-07-15): this used to close the GAME listener here
// (shutdown/closesocket(gameListenerSocket)) on a CONSOLE disconnect -- a
// naming bug: the comment above + the commented-out OpenConnection below
// intended to re-post a CONSOLE listen, which CreateConsoleHost() (below)
// already does. Closing the game listener on console loss needlessly
// bounced the game-accept path (harmless to already-established peer
// sockets -- which is why a live 2-node match keeps replicating through a
// console loss -- but wrong, and it would have blocked a NEW peer from
// joining after a console cycle). Removed; CreateConsoleHost re-listens.
//unsigned long console_socket = OpenConnection(
// NETNUB_TCP_LISTEN,
// ((L4Application *)application)->GetNetworkCommonFlatAddress(), // Local port