From 2e819f7c5e0fb6352908ca88ff09b3465023767c Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Fri, 4 Sep 2026 01:47:34 +0200 Subject: fix(node): select the Windows-compatible event loop before asyncio.run aiortc's ICE stack does not run on Windows' default ProactorEventLoop -- a DataChannel handshake never completes. `platform.use_compatible_event_loop()` switches to the SelectorEventLoop on win32, called at the top of `main()` before `asyncio.run()`. No-op off Windows. Known cost, for when the node runs on Windows: the SelectorEventLoop cannot spawn subprocesses, so ffmpeg streaming (asyncio.create_subprocess_exec in webrtc_server.py) needs a thread-based runner there. Tracked separately. Co-Authored-By: Claude Sonnet 5 --- packages/meshbay-node/src/meshbay_node/daemon.py | 3 +++ packages/meshbay-node/src/meshbay_node/platform.py | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/packages/meshbay-node/src/meshbay_node/daemon.py b/packages/meshbay-node/src/meshbay_node/daemon.py index 47241cd..d616b0c 100644 --- a/packages/meshbay-node/src/meshbay_node/daemon.py +++ b/packages/meshbay-node/src/meshbay_node/daemon.py @@ -1634,6 +1634,9 @@ def _systemctl_user(verb: str, unit: str, *, not_running_hint: str, def main() -> None: import argparse + from meshbay_node.platform import use_compatible_event_loop + use_compatible_event_loop() + parser = argparse.ArgumentParser(description="MeshBay Node daemon") parser.add_argument("command", nargs="?", choices=["init", "reset", "status", "gek-init", diff --git a/packages/meshbay-node/src/meshbay_node/platform.py b/packages/meshbay-node/src/meshbay_node/platform.py index bc48169..4bd8e35 100644 --- a/packages/meshbay-node/src/meshbay_node/platform.py +++ b/packages/meshbay-node/src/meshbay_node/platform.py @@ -1,10 +1,29 @@ """Platform-specific paths and tool resolution for meshbay-node.""" +import asyncio import os import shutil import sys from pathlib import Path +# ── Event loop ─────────────────────────────────────────────────────────────── + + +def use_compatible_event_loop() -> None: + """ + aiortc's ICE stack (aioice) does not run on Windows' default + ProactorEventLoop — a DataChannel handshake never completes and the + connection hangs. Select the SelectorEventLoop before the loop is created. + + Cost: SelectorEventLoop cannot spawn subprocesses on Windows, so ffmpeg + streaming (asyncio.create_subprocess_exec in webrtc_server.py) does not work + under it. The video path needs a thread-based runner on Windows — tracked + for the port. No effect off Windows. + """ + if sys.platform == "win32": + asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) + + # ── Directories ────────────────────────────────────────────────────────────── -- cgit v1.2.3