Setup
OS: Windows 11 with latest updates, and Windows containers installed with containerd as per https://learn.microsoft.com/en-us/virtualization/windowscontainers/quick-start/set-up-environment?tabs=containerd but with the following version updates:
- containerd version v2.2.0
- nerdctl version v2.3.4 (from git)
- hcsshim version spec: v1.3.0 (from git)
Description
I've been investigating why running a WCOW container using nerdctl run -d -t mcr.microsoft.com/windows/server:ltsc2025 terminates almost immediately with exit code 3221225786 (0xc000013a) STATUS_CONTROL_C_EXIT as reported at containerd/nerdctl#4899, and the best conclusion I have reached so far is that the underlying HcsProcess requires a valid non-NULL Stdin handle to avoid this immediate termination.
Analysis
Looking at the original issue reported with nerdctl above, with the latest git versions of nerdctl and hcsshim I see the following behaviour:
C:\Users\mark>nerdctl run -d -t mcr.microsoft.com/windows/nanoserver:ltsc2025
369992f8d96f29ab0412dc800b3eff24c8a3a29596bbf5ba3629450f2dd709fc
C:\Users\mark>nerdctl ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
369992f8d96f mcr.microsoft.com/windows/nanoserver:ltsc2025 "c:\\windows\\system32…" 5 seconds ago Exited (3221225786) 2 seconds ago nanoserver-36999
For comparison we can see that starting the same container in interactive mode works fine:
C:\Users\mark>nerdctl run --rm -it mcr.microsoft.com/windows/nanoserver:ltsc2025
Microsoft Windows [Version 10.0.26100.32860]
(c) Microsoft Corporation. All rights reserved.
C:\Windows\System32>echo "Hello world"
"Hello world"
C:\Windows\System32>exit
time="2026-07-20T09:52:06+01:00" level=warning msg="failed to remove hosts file for container \"163f0d294c723af096f2965253e16e226a7be00a3a4d8d1cdc93bc152776f251\"" error="hosts-store error\nnot found\nGetFileAttributesEx C:\\ProgramData\\nerdctl\\052055e3\\etchosts\\default\\163f0d294c723af096f2965253e16e226a7be00a3a4d8d1cdc93bc152776f251: The system cannot find the file specified."
C:\Users\mark>
I added various debug statements around nerdctl/hcsshim/containerd and the only obvious difference I could see was that in the detached terminal case the HcsProcess Stdin was set to NULL compared with the interactive terminal.
To test this theory I made the following simple change to hcsshim to see what would happen to the working interactive terminal if I hardcoded the HcsProcess Stdin to NULL:
diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go
index 82f859d5..8b8aa20c 100644
--- a/internal/cmd/cmd.go
+++ b/internal/cmd/cmd.go
@@ -180,7 +180,7 @@ func (c *Cmd) Start() error {
User: c.Spec.User.Username,
WorkingDirectory: c.Spec.Cwd,
EmulateConsole: c.Spec.Terminal,
- CreateStdInPipe: c.Stdin != nil,
+ CreateStdInPipe: false,
CreateStdOutPipe: c.Stdout != nil,
CreateStdErrPipe: c.Stderr != nil,
}
With this change we can see that the container that was previously working in interactive mode now fails in exactly the same, even to the point where the Ctrl-C character is visible in the terminal itself:
C:\Users\mark>nerdctl run -it mcr.microsoft.com/windows/nanoserver:ltsc2025
^C
C:\Users\mark>nerdctl ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a141fb818e6e mcr.microsoft.com/windows/nanoserver:ltsc2025 "c:\\windows\\system32…" About a minute ago Exited (3221225786) About a minute ago nanoserver-a141f
So why is it necessary to provide a non-NULL handle to the HcsProcess Stdin only in the detached terminal case? The answer to this is because when nerdctl creates a detached terminal, it uses a new upstream BinaryIO which only creates pipes for Stdout/Stderr and not Stdin as per https://github.com/microsoft/hcsshim/blob/main/internal/cmd/io_binary.go#L33.
At this point my thoughts were that any HcsProcess must have a non-zero Stdin handle, however with the above patch applied to hcsshim I see something interesting: if I run a command such as nerdctl run --rm -it mcr.microsoft.com/windows/nanoserver:ltsc2025 cmd.exe /? enough times in a loop from cmd.exe then eventually it will succeed after perhaps 20-30 tries.
This suggests that it may not necessarily be the NULL Stdin handle that is directly responsible for the failure, but somehow hcsshim accidentally depends upon a functional Stdin in order to detect a successful WCOW container startup and process HcsProcess launch.
Summary
There is a currently an issue when launching detached containers from nerdctl using nerdctl run -d -t mcr.microsoft.com/windows/nanoserver:ltsc2025 causing the process to fail immediately with exit code 3221225786 (0xc000013a) STATUS_CONTROL_C_EXIT. This is linked to the presence of a valid non-NULL Stdin handle for the container HcsProcess which is likely to have one of two causes:
- Console applications launched as a HcsProcess MUST have a valid non-NULL Stdin handle
This would require someone with Windows internal knowledge to confirm the expectations and behaviour of console applications such as cmd.exe when presented with a NULL Stdin handle. If all console applications MUST have a valid non-NULL Stdin handle then hcsshim should always create the Stdin pipe for a HcsProcess (even if it is never connected) which will resolve the issue.
- Hcsshim inadvertently depends upon a valid Stdin handle to detect a successful HcsProcess launch
There may be logic in hcsshim that assumes a valid Stdin handle is always present to detect a successful HcsProcess launch: if a valid Stdin handle is not present then a racy logic condition in hcsshim may attempt to detect this and cause the HcsProcess to terminate immediately. For a detached container launched with nerdctl with BinaryIO, a Stdin pipe is never created for the HcsProcess causing the failure.
Setup
OS: Windows 11 with latest updates, and Windows containers installed with containerd as per https://learn.microsoft.com/en-us/virtualization/windowscontainers/quick-start/set-up-environment?tabs=containerd but with the following version updates:
Description
I've been investigating why running a WCOW container using
nerdctl run -d -t mcr.microsoft.com/windows/server:ltsc2025terminates almost immediately with exit code 3221225786 (0xc000013a)STATUS_CONTROL_C_EXITas reported at containerd/nerdctl#4899, and the best conclusion I have reached so far is that the underlying HcsProcess requires a valid non-NULL Stdin handle to avoid this immediate termination.Analysis
Looking at the original issue reported with nerdctl above, with the latest git versions of nerdctl and hcsshim I see the following behaviour:
For comparison we can see that starting the same container in interactive mode works fine:
I added various debug statements around nerdctl/hcsshim/containerd and the only obvious difference I could see was that in the detached terminal case the HcsProcess Stdin was set to NULL compared with the interactive terminal.
To test this theory I made the following simple change to hcsshim to see what would happen to the working interactive terminal if I hardcoded the HcsProcess Stdin to NULL:
With this change we can see that the container that was previously working in interactive mode now fails in exactly the same, even to the point where the Ctrl-C character is visible in the terminal itself:
So why is it necessary to provide a non-NULL handle to the HcsProcess Stdin only in the detached terminal case? The answer to this is because when nerdctl creates a detached terminal, it uses a new upstream BinaryIO which only creates pipes for Stdout/Stderr and not Stdin as per https://github.com/microsoft/hcsshim/blob/main/internal/cmd/io_binary.go#L33.
At this point my thoughts were that any HcsProcess must have a non-zero Stdin handle, however with the above patch applied to hcsshim I see something interesting: if I run a command such as
nerdctl run --rm -it mcr.microsoft.com/windows/nanoserver:ltsc2025 cmd.exe /?enough times in a loop from cmd.exe then eventually it will succeed after perhaps 20-30 tries.This suggests that it may not necessarily be the NULL Stdin handle that is directly responsible for the failure, but somehow hcsshim accidentally depends upon a functional Stdin in order to detect a successful WCOW container startup and process HcsProcess launch.
Summary
There is a currently an issue when launching detached containers from nerdctl using
nerdctl run -d -t mcr.microsoft.com/windows/nanoserver:ltsc2025causing the process to fail immediately with exit code 3221225786 (0xc000013a)STATUS_CONTROL_C_EXIT. This is linked to the presence of a valid non-NULL Stdin handle for the container HcsProcess which is likely to have one of two causes:This would require someone with Windows internal knowledge to confirm the expectations and behaviour of console applications such as cmd.exe when presented with a NULL Stdin handle. If all console applications MUST have a valid non-NULL Stdin handle then hcsshim should always create the Stdin pipe for a HcsProcess (even if it is never connected) which will resolve the issue.
There may be logic in hcsshim that assumes a valid Stdin handle is always present to detect a successful HcsProcess launch: if a valid Stdin handle is not present then a racy logic condition in hcsshim may attempt to detect this and cause the HcsProcess to terminate immediately. For a detached container launched with nerdctl with BinaryIO, a Stdin pipe is never created for the HcsProcess causing the failure.