btconsole: survive socket errors + flush output (the mid-session sync-freeze lead)

The console emulator's recv loop only caught socket.timeout -- any reset/abort killed
the thread UNHANDLED, its buffered stdout died with it, and with both threads gone the
process exited silently.  The 2-node session then froze replication BOTH ways (each pod
holding a dead ConsoleHost socket; the engine never logged a console disconnect).  Now:
OSErrors are caught + logged and the thread idles alive; prints flush.  Run with
python -u and > console.log to capture the death reason on any recurrence.  The engine-
side question (why a dead console freezes peer replication + the disconnect handler's
gameListenerSocket-vs-consoleListenerSocket close) is logged in open-questions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-14 09:30:47 -05:00
co-authored by Claude Fable 5
parent 02ce55194e
commit 8674bca2d8
+9 -1
View File
@@ -122,7 +122,7 @@ def serve_pod(hostport, egg_bytes):
try:
data = s.recv(4096)
if not data:
print(f"[{name}] pod closed the console socket")
print(f"[{name}] pod closed the console socket", flush=True)
return
# Expect the AcknowledgeEggFile (and possibly other console traffic).
if len(data) >= 24:
@@ -134,6 +134,14 @@ def serve_pod(hostport, egg_bytes):
print(f"[{name}] pod->console {len(data)} bytes")
except socket.timeout:
continue
except OSError as e:
# Previously UNHANDLED: a reset/abort here killed the thread silently
# (buffered stdout lost) and the console process exited -- leaving the
# pods holding dead console sockets. Log it and keep the thread alive
# (idle) so the process + diagnosis survive.
print(f"[{name}] console socket error: {e!r} -- idling", flush=True)
while True:
time.sleep(60)
def main():