<feed xmlns='http://www.w3.org/2005/Atom'>
<title>meshbay.git/packages/meshbay-node/tests/test_windows_service_diagnosis.py, branch main</title>
<subtitle>MeshBay — read-only public mirror</subtitle>
<id>https://git.meshbay.org/meshbay.git/atom?h=main</id>
<link rel='self' href='https://git.meshbay.org/meshbay.git/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/'/>
<updated>2026-09-27T20:20:35Z</updated>
<entry>
<title>fix(node): a Windows daemon that stops properly, starts honestly and runs once</title>
<updated>2026-09-27T20:20:35Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-09-27T20:20:35Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=7662484cae8e74b7d9aa383bd6cd0dad4690aadc'/>
<id>urn:sha1:7662484cae8e74b7d9aa383bd6cd0dad4690aadc</id>
<content type='text'>
Found by installing the builds and driving every startup mode live:

- Stop through the node's own control API first (POST /api/shutdown, loopback
  and per-run token): the one channel that reaches a daemon in any session
  without elevation -- a service node runs in session 0 -- and the one that
  runs its shutdown. Then Task Scheduler, then a forced stop. Nine stops in a
  row used to log no shutdown at all: each was a TerminateProcess.
- The forced stop spares the command running it. The frozen meshbay-node.exe
  is the daemon and every CLI verb, so `taskkill /IM meshbay-node.exe` killed
  `autostart stop` and `restart-daemon` themselves: exit 1, no output, and no
  node after a restart. It excludes its own pid and its parent's, and /T takes
  a venv launcher's python child and a daemon's ffmpeg children with it.
- Start and restart report the version that answered, never "started" about a
  node nobody asked; `service start` says so when no node answered, and where
  the log is.
- A second instance fails before it touches anything. The daemon wrote
  ui-token, then failed to bind inside uvicorn's task and exited with the
  reason on a hidden console; the node still running then refused every stop
  and status, its token file naming a dead process. The control port is now
  bound first (exclusively on Windows, where SO_REUSEADDR would share it), and
  a refusal is logged and exits 2. Linux had the same order.
- The daemon logs to %LOCALAPPDATA%\meshbay\state\node.log: Task Scheduler
  discards its stderr. Only the daemon run opens it, never a CLI verb.
- Hub sign-in waits are interruptible, a stop requested before the node is up
  is honoured, and a hub that answers 429 or restarts leaves the node in
  waiting_for_hub rather than looking dead.
- operator_paired is null until the roster is read, instead of a false that
  showed "No operator paired" about a node whose pairing was intact.

The node test conftest also points HOME, USERPROFILE, LOCALAPPDATA and APPDATA
at a throwaway directory for every test, and keeps log_file() away from the
developer's own node: redirecting HOME alone isolates nothing on Windows, and
the CLI tests had been writing invite and pairing codes into the real profile.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
</feed>
