Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Stdin handle required to avoid conpty race condition upon WCOW container startup with terminal

未关闭
#2,831 3 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
42/100
Issue 类型
缺陷
描述清晰度
需要澄清
活跃度
冷清
技术栈
go

调研方向

从 internal/cmd/cmd.go 开始,重点查看 Cmd.Start 和 CreateStdInPipe 的决策,然后将其与 internal/cmd/io_binary.go 中分离终端的 BinaryIO 行为进行比较。使用 nerdctl run -d -t 重现 WCOW 失败,并与交互式启动进行比较;确定是缺少 stdin 句柄还是 hcsshim 启动检测导致竞态,并处理已确认的原因后,即视为完成。

由索引模型根据 Issue 内容生成。

描述

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 https://github.com/containerd/nerdctl/issues/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.

主要语言
Go
星标
694
派生
304
平均合并
1 天 19 小时
30 天内合并 PR
28

贡献指南

这个仓库没有索引到贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

microsoft/hcsshim 的其他 Issue

查看 microsoft/hcsshim 的全部 Issue

相似的 Issue

更多 Go Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。