docs(installer): correct the Windows service decision, and the 1053 advice
PLAN.md §8 recorded that `sc create` against the plain console sidecar worked and needed no change to `link`. The first Windows install disproved it: 1053, "a timeout was reached (30000 milliseconds) while waiting for the service to connect", with SERVICE_EXIT_CODE 0. The premise was a false symmetry with systemd. systemd supervises any foreground process; the Windows SCM supervises only one that calls StartServiceCtrlDispatcher within ~30 seconds. Record the reversal and what it costs: link gains a Windows service entry point, kept at the edges so the whole sidecar stays shared and Cargo builds neither Windows crate for Linux. INSTALL.md: - Troubleshooting gains a 1053 row naming the real cause (a sidecar older than v1.2.0) and the two tell-tales that distinguish it from a crash: exit code 0, and a foreground run of the same binary working fine. - The existing "stops immediately" row said the same wrong thing; it now covers the genuine-crash case only, and points at the log file and journalctl. - §3 and Appendix A4 document the service log, and A4 states the version floor. - Fixes a literal 0x08 byte in the backups path row, which rendered as `%ProgramData%\RunicGatewayackups\` — the backslash had been eaten. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1284,15 +1284,42 @@ mismatched pair from being published as a bundle — which is the mechanism that
|
||||
different host, or hard-assume co-location?
|
||||
Resolved and moved into §1 / §2.2 / §5: uninstall scope, and minimum ServUO version.
|
||||
|
||||
**Resolved — Windows service mechanism** (was question 1). `sc create` against the plain console
|
||||
binary, as recommended: it works on a stock host, ships nothing extra, and needs no change to
|
||||
`link`. A WinSW/NSSM shim would be a third binary to keep current, and a native `--service` mode
|
||||
using the `windows-service` crate would put Windows service plumbing inside a component whose whole
|
||||
job is being platform-agnostic. Restart semantics turned out to be adequate —
|
||||
`sc failure … actions= restart/5000` is the direct counterpart of systemd's `Restart=on-failure` /
|
||||
`RestartSec=5`. What the recommendation did *not* anticipate is the service identity: plain
|
||||
`sc create` runs as `LocalSystem`, so Phase 2 registers with `obj= "NT SERVICE\RunicGatewayLink"`
|
||||
instead (see [Phase 2 as built](#phase-2--uo-link-install-and-service)).
|
||||
**Resolved — Windows service mechanism** (was question 1). Registration is `sc create` with
|
||||
`obj= "NT SERVICE\RunicGatewayLink"` (plain `sc create` would run as `LocalSystem`, which the Linux
|
||||
half pointedly does not do), `sc failure … actions= restart/5000` as the counterpart of systemd's
|
||||
`Restart=on-failure` / `RestartSec=5`, and the config pinned in `binPath` rather than in a
|
||||
machine-wide environment variable. No WinSW/NSSM shim: that would be a third binary to keep current.
|
||||
|
||||
**Corrected 2026-08-07 — the sidecar needs its own service mode after all.** This section previously
|
||||
recorded that `sc create` against the *plain console binary* worked and needed no change to `link`.
|
||||
It does not, and the first Windows run proved it: `sc start` failed with **1053** and the event log
|
||||
read *"a timeout was reached (30000 milliseconds) while waiting for the … service to connect"*,
|
||||
with `SERVICE_EXIT_CODE : 0` — the process had started fine and simply never spoke to the SCM.
|
||||
|
||||
The premise was a false symmetry with systemd. systemd supervises *any* foreground process; the
|
||||
Windows SCM supervises only a process that calls `StartServiceCtrlDispatcher` within ~30 seconds and
|
||||
then reports its own state transitions. There is no third option where `sc.exe` adopts an arbitrary
|
||||
console executable — it is a service-aware binary or a shim, and the shim was already rejected.
|
||||
|
||||
So `link` gains a Windows service entry point (the `windows-service` crate, behind
|
||||
`[target.'cfg(windows)'.dependencies]`). The objection that this puts Windows plumbing inside a
|
||||
platform-agnostic component is answered by keeping it *only* at the edges: `app::run` is the whole
|
||||
sidecar and is shared, while `windows.rs` and `unix.rs` do nothing but start it and tell it when to
|
||||
stop. Nothing platform-specific reaches the shared path, and Cargo neither resolves nor builds the
|
||||
Windows crates for Linux.
|
||||
|
||||
Consequences worth knowing:
|
||||
|
||||
- **One binary, no `--service` flag.** The dispatcher is tried first; failing with
|
||||
`ERROR_FAILED_SERVICE_CONTROLLER_CONNECT` (1063) means "not started by the SCM" and falls through
|
||||
to a normal foreground run. `cargo run` and a hand-run diagnostic are unchanged.
|
||||
- **A service has no stdout**, so in service mode the sidecar logs to a daily-rolled file beside its
|
||||
config instead of into the void.
|
||||
- **`Running` is reported only once the shard port is bound and the store is open**, so a bad config
|
||||
fails the *start* rather than flapping Running → Stopped, and a failed run leaves a nonzero
|
||||
`SERVICE_EXIT_CODE` behind rather than the misleading `0` above.
|
||||
- **A sidecar older than v1.2.0 can never start as a service on Windows**, however good its config.
|
||||
The installer says so by name when it sees 1053.
|
||||
|
||||
**Resolved — branch targeting for the new repo** (was question 4). The v3 cutover landed:
|
||||
`servuo-plugins#6` merged, so that repo's `main` and `edge` agree at protocol 3. The release
|
||||
|
||||
Reference in New Issue
Block a user