# Windows x64 late-slope soak (lmxopcua#799 acceptance) Owner scope 2026-11-12: #799 acceptance covers the deployment platforms, Windows x64 and Linux. This folder runs the **same canonical test** as the Linux late-slope run (`Sdk2LifecycleSoakTests.Repeated_lifecycles_return_resources_to_a_steady_baseline`, `OTOPCUA_SDK2_SOAK_MODE=late-slope`, 7,200 s) on Windows x64 with the protocol unchanged: cycle-3 cold baseline, +64 MiB retained managed / +128 MiB RSS / +32 descriptors, first-rejection latch with every canonical cycle and restart continuing, ownership/logical/operation/shutdown failures fatal, certificate leak tracking on, the same startup/cycle/restart/shutdown bounds, and the same fixed windows and least-squares report (`analyze.py` imports `../late-slope/analyze.py` and only switches its expected architecture to `X64`). ## Windows adaptations | Linux element | Windows equivalent | Why | |---|---|---| | RSS = `Process.WorkingSet64` (= `VmRSS`) | **Working set**, the same `Process.WorkingSet64` call, unchanged test code | Resident physical pages of the process, the direct analog of Linux RSS. Private bytes (commit charge) counts committed-but-not-resident memory and pagefile-backed pages, so it is not comparable to RSS; the launcher records it externally every 30 s as a descriptive series only. | | Descriptors = entries of `/proc/self/fd` | **Every handle in the process handle table** (`NtQuerySystemInformation(SystemExtendedHandleInformation)`, own PID) | Windows has no fd table; the handle table is the per-process kernel-resource table. It is broader than Linux fds (threads, events, keys, sections), so the unchanged +32 cap is if anything stricter. | | PKI descriptors = fds whose link target lies under a PKI root | Disk-file/directory handles (`GetFileType = DISK`) whose `GetFinalPathNameByHandle` path lies under a root; roots canonicalised the same way, compared case-insensitively | Final paths resolve symlinks, junctions, 8.3 names and casing (the Windows analog of the macOS `/var`→`/private/var` lesson). | | Probe bound: lsof child 5 s | Enumeration on a dedicated thread, 5 s bound; a blocked name query is a `TimeoutException`, never a favourable zero | Name queries can block on synchronous handles; only disk handles are name-queried. | | Descriptor controls (symlink alias open/close; probe timeout reaps `/bin/sh`) | Same two tests, Windows enabled: `Directory.CreateSymbolicLink` alias (Developer Mode / elevated); the timeout control runs `cmd.exe` holding both pipes open behind a 30 s `ping` | Must execute 2/2 before the canonical test starts, as in `container.sh`. | | Container: read-only root, `--network none`, private `/task` | Fresh private task directory (inheritance removed; user + SYSTEM) holding `TEMP`/`TMP`, CLI home, results and fixture PKI; loopback-only fixture; machine otherwise idle | No Windows container runtime on the deployment-class host. | | `/proc//exe` + mapped `libcoreclr.so` check | Target PID's image must be the bundle `…IntegrationTests.exe` and `coreclr.dll` must be mapped from the bundle with the receipt hash | Same proof that the self-contained 10.0.14 runtime is the one measured. | | Container outer deadline 7,440 s | Launcher kills only the task-owned process tree at 7,440 s | Same bound. | | — | External sampler: working set, private bytes, handle count, threads every 30 s; MxAccessGw readiness every 5 min | Descriptive diagnostics and proof the co-hosted service stayed healthy. Not gated. | `LateSlopeRun.ValidateRequest` accepts Linux ARM64 or Windows x64 (owner scope); the 7,200 s duration, runtime 10.0.14 and leak-tracking requirements are unchanged. ## Run ```bash python3 scripts/validation/opcua-lifecycle-memory/windows/prepare.py --source-revision "$rev" --output "$bundle" # copy the bundle to the Windows host (COPYFILE_DISABLE=1 tar on macOS), then on the host: powershell -NoProfile -ExecutionPolicy Bypass -File "$bundle\tools\launch.ps1" -Bundle "$bundle" -Output "$run" -SourceRevision "$rev" # copy the run back, then: python3 "$bundle/tools/analyze.py" --run "$run" --bundle-receipt "$bundle/receipt.json" --source-revision "$rev" ``` Launch the PowerShell launcher detached from any SSH session (e.g. `Win32_Process.Create`), because Win32-OpenSSH terminates a session's job object on disconnect.