Tracked deferral from the up --auto-forward feature (spec 015-auto-forward-ports, task T054; shipped in #188). v1 is Unix-only; this adds Windows host support for the detached forwarder.
Goal / acceptance
deacon up --auto-forward detaches a forwarder and is reaped correctly on Windows hosts (same external behavior as Unix).
Hidden issues / gotchas
- No
setsid/dup2/kill on Windows. The Unix path (crates/core/src/port_forward/daemon.rs) re-exec's the child and has it call nix::unistd::setsid() then dup2 its own stdio onto the per-container log. Windows has no session/dup2-self-redirect equivalent.
- Detach model is inverted. On Windows the cleaner approach is the parent spawning the child already-detached:
std::os::windows::process::CommandExt::creation_flags(DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP) with the child's stdio redirected to the log at spawn time (crates/deacon/src/commands/up/forward.rs::spawn_daemon). So daemon::daemonize() becomes a near-noop on Windows.
- Signaling differs.
pid_alive/terminate_pid can't use POSIX signals — need OpenProcess/GetExitCodeProcess for liveness and TerminateProcess (or GenerateConsoleCtrlEvent for a graceful path) for reaping, via windows/windows-sys gated cfg(windows).
- Cannot be behaviorally verified in our Linux+Docker CI. GitHub-hosted
windows-latest runners can't run our Linux-container Docker integration tests — see the disabled matrix entry in .github/workflows/ci.yml ("Windows disabled until bespoke runner with Docker support is available"). We do already build the Windows deliverable on windows-latest in release.yml (MSVC targets + a deacon.exe --version smoke run).
Recommended path forward
- Implement a
#[cfg(windows)] detach/signaling path: parent-side detached spawn + stdio→log redirect; OpenProcess/TerminateProcess-based liveness/terminate; daemonize() no-op.
- Add a
windows-latest CI job to ci.yml that runs cargo build + the hermetic unit tests (parser, registry loopback-bind allocation, attributes, marker, new Windows process-helper unit tests). This is a compile + unit gate — it catches the bulk of breakage pre-launch even though it can't run the Docker e2e path.
- Land it as "CI-validated, not behaviorally verified" until a Docker-capable Windows runner exists; track the e2e verification as a sub-task.
Out of scope
Behavioral e2e validation on Windows (blocked on a Docker-capable Windows runner).
Tracked deferral from the
up --auto-forwardfeature (spec015-auto-forward-ports, task T054; shipped in #188). v1 is Unix-only; this adds Windows host support for the detached forwarder.Goal / acceptance
deacon up --auto-forwarddetaches a forwarder and is reaped correctly on Windows hosts (same external behavior as Unix).Hidden issues / gotchas
setsid/dup2/killon Windows. The Unix path (crates/core/src/port_forward/daemon.rs) re-exec's the child and has it callnix::unistd::setsid()thendup2its own stdio onto the per-container log. Windows has no session/dup2-self-redirect equivalent.std::os::windows::process::CommandExt::creation_flags(DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP)with the child's stdio redirected to the log at spawn time (crates/deacon/src/commands/up/forward.rs::spawn_daemon). Sodaemon::daemonize()becomes a near-noop on Windows.pid_alive/terminate_pidcan't use POSIX signals — needOpenProcess/GetExitCodeProcessfor liveness andTerminateProcess(orGenerateConsoleCtrlEventfor a graceful path) for reaping, viawindows/windows-sysgatedcfg(windows).windows-latestrunners can't run our Linux-container Docker integration tests — see the disabled matrix entry in.github/workflows/ci.yml("Windows disabled until bespoke runner with Docker support is available"). We do already build the Windows deliverable onwindows-latestinrelease.yml(MSVC targets + adeacon.exe --versionsmoke run).Recommended path forward
#[cfg(windows)]detach/signaling path: parent-side detached spawn + stdio→log redirect;OpenProcess/TerminateProcess-based liveness/terminate;daemonize()no-op.windows-latestCI job toci.ymlthat runscargo build+ the hermetic unit tests (parser, registry loopback-bind allocation, attributes, marker, new Windows process-helper unit tests). This is a compile + unit gate — it catches the bulk of breakage pre-launch even though it can't run the Docker e2e path.Out of scope
Behavioral e2e validation on Windows (blocked on a Docker-capable Windows runner).