Skip to content

Cmd::exec can close an unrelated descriptor after stdin is consumed #2159

Open

Description

@iloveeyjafjalla

Cmd::exec closes the nonempty stdin pipe after all bytes are sent, but leaves that descriptor number in stdinPipe[1]. The scope cleanup closes the same number again after the child exits. If another thread opens a file in this interval, Linux can reuse that number and the cleanup closes the unrelated new descriptor.

The production path ContainerCfgBuilder::applyExecutablePatch uses Cmd(patchFile).toStdin(OCI config JSON).exec(). This report concerns successful consumption of stdin, independent of the SIGPIPE problem tracked in #1931/#1926.

Baseline: master@0fee1e07d6b465ed3259822538189f2c5ecccae6.

A real-process regression uses Cmd -> /bin/sh -> /bin/cat. The child consumes stdin to EOF and signals readiness; a second thread opens 16 /dev/null descriptors, then releases the child to exit. After the successful command returns, fcntl(F_GETFD) finds one of those descriptors closed:

command.toStdinKeepsDescriptorsOpenedAfterInputEof
closedByCommand: 1
Expected: 0
Trace: nonempty input

Empty stdin is a control: that existing branch already clears stdinPipe[1] and does not close the unrelated descriptors.

Expected: a command's cleanup should only close descriptors it still owns.

The minimal fix clears stdinPipe[1] to -1 immediately after closing it on the completed-input path, matching the existing empty-input branch. See the Linux close(2) discussion of multithreaded descriptor reuse.

Related open changes were inspected by their actual head diffs: #1926 handles SIGPIPE; #2068 validates executable commands; #2122 fixes PipeSet parent/child ends. None clears this completed-input descriptor.

AI assistance: prepared with OpenAI Codex. Reproduction uses real Linux child processes, pipes, threads, open, close and fcntl calls. Complete validation results will be documented in the linked fix PR; no full container/deployment validation is claimed.

Activity

  1. iloveeyjafjalla commented on Oct 10, 2026

    @iloveeyjafjalla
    Author

    Fix PR: #2160

    This PR contains the minimal stdin descriptor ownership fix and the real-process regression test. Validation and AI disclosure are in the PR description.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions