OXYGENHUB

A Windows runner reports its Windows version f4dfd742b30d

As its kernel fact, from RtlGetVersion. Not yet run on Windows.

refs #83
Author
Andy McCall @andymccall <[email protected]>
via
agent agent:claude@andymccall <[email protected]> · keyless, under your grant for changes,refs,seal · key 936f2987b45f
When
· 2026-10-26 03:59 UTC
Signature
◈ sealed by agent:claude@andymccall
Hash
f4dfd742b30df3764874975863da9d780d729d5c9fb543989c49ba1adc7c3189
Depends on
337afb8f6043 3554afefb6aa 494a1b9a8ac2 4dd392d16454 62829d15ef09 6f66e397539c c3db750ed96e e0918b887850
Depended on by
cce63af9ec54
In bookmarks
main
In tags
v0.4.0 v0.5.0 v0.5.1 v0.5.2 v0.5.3
Edits
7 atoms, 0 tree operations, 3 files

Browse the tree at this change

modified CHANGELOG.md +1 −0
…
3 unchanged lines
4 4
5 5
## Unreleased
6 6
7 +
- **A Windows runner reports its Windows version (#83):** as its kernel fact (`Windows 10.0.26100`, from `RtlGetVersion`), shown on the hub's runner page and in `flow runner bench`. Built and linted for Windows; not yet run there.
7 8
- **`flow runner drain` (#83):** asks the home's running runner to drain, as SIGTERM does on Linux, through a `drain.request` file its loop reads: the way to stop a Windows runner without losing its job. A starting runner clears a stale request.
8 9
- **A Windows runner updates itself (#83, #85):** `flow runner update` on Windows checks a PE build, renames `flow.exe` to `flow.prev.exe` and `flow.new.exe` into its place with `MoveFileExW` (retrying while a virus scanner holds a new file; a running program cannot rename its own file, so a copy of it, `flow __rename`, does), tells the running runner through an `update.request` file in its home (no SIGUSR1 there), and the runner leaves and exits 75 so a Task Scheduler task set to restart on failure starts the new build, which proves itself by reaching the hub. Tried in the Windows VM: install, leave, exit 75, restart, proven. A rollback runs the restored build and ends with it. Spec §11.5.3.
9 10
- **`flow` builds for Windows (#83, step 2 begun):** `cargo build --target x86_64-pc-windows-gnu` gives a `flow.exe` that offers the WASM tier: the syscall tier, the guest helpers and the egress proxy are Linux's only (a Windows build says the syscall tier "runs only on Linux"), cache pruning by reads stays on Linux, and file modes, links and sizes go through a small `portable` module (modes are not kept on Windows). Its claims report free disk (`GetDiskFreeSpaceExW`); load and kernel are not measured there yet, and a Windows runner does not update itself. `dist` builds `flow-windows-x86_64.exe` too. Nothing changes on Linux or Android. Tried in the Windows VM on Earth: `flow.exe tiers` offers wasm, a local `flow run` of a 120-step WASM job passes, and registered as runner `windows-1` (label `windows`) it ran andymccall/windows-runner-demo's job from the hub (run #1). Helpers start from the running binary's path on Windows (`/proc/self/exe` on Linux and Android).
…
102 unchanged lines
modified crates/flow/Cargo.toml +3 −2
…
33 unchanged lines
34 34
wasmtime = { version = "=49.0.4", default-features = false, features = ["cranelift", "runtime", "std", "parallel-compilation"] }
35 35
wasmtime-wasi = { version = "=49.0.4", default-features = false, features = ["p1"] }
36 36
37 -
# A Windows runner's free disk and renaming a running flow.exe (oxygenflow#83);
37 +
# A Windows runner's free disk, version, and renaming a running flow.exe
38 +
# (oxygenflow#83);
38 39
# already in the tree through wasmtime.
39 40
[target.'cfg(windows)'.dependencies]
40 -
windows-sys = { version = "0.61", features = ["Win32_Storage_FileSystem"] }
41 +
windows-sys = { version = "0.61", features = ["Win32_Foundation", "Win32_Storage_FileSystem", "Win32_System_SystemInformation", "Wdk_System_SystemServices"] }
41 42
42 43
[dev-dependencies]
43 44
tempfile.workspace = true
…
2 unchanged lines
modified crates/flow/src/facts.rs +10 −3
…
22 unchanged lines
23 23
24 24
/// The kernel's release, as uname says. Not read from /proc: an Android
25 25
/// app may not read it there, and is refused (and logged) every claim.
26 -
/// None on Windows (oxygenflow#83).
27 26
#[cfg(unix)]
28 27
pub fn kernel() -> Option<String> {
29 28
    let mut u: libc::utsname = unsafe { std::mem::zeroed() };
…
6 unchanged lines
36 35
    Some(release.to_string_lossy().into_owned())
37 36
}
38 37
39 -
#[cfg(not(unix))]
38 +
/// Windows' version (`Windows 10.0.26100`), from `RtlGetVersion`, which
39 +
/// unlike `GetVersionEx` does not depend on the program's manifest.
40 +
#[cfg(windows)]
40 41
pub fn kernel() -> Option<String> {
41 -
    None
42 +
    use windows_sys::Win32::System::SystemInformation::OSVERSIONINFOW;
43 +
    // SAFETY: an all-zero OSVERSIONINFOW is valid; its size is set before the call.
44 +
    let mut v: OSVERSIONINFOW = unsafe { std::mem::zeroed() };
45 +
    v.dwOSVersionInfoSize = std::mem::size_of::<OSVERSIONINFOW>() as u32;
46 +
    // SAFETY: `v` is a writable OSVERSIONINFOW with its size set.
47 +
    let status = unsafe { windows_sys::Wdk::System::SystemServices::RtlGetVersion(&mut v) };
48 +
    (status == 0).then(|| format!("Windows {}.{}.{}", v.dwMajorVersion, v.dwMinorVersion, v.dwBuildNumber))
42 49
}
43 50
44 51
/// Free space for an unprivileged writer on the file system holding `path`,
…
120 unchanged lines