Skip to content

Treat a missing log file as empty in container logs - #2393

Merged
jglogan merged 1 commit into
apple:mainfrom
bryanmosley:fix/logs-missing-files
Oct 15, 2026
Merged

jglogan merged 1 commit into
apple:mainfrom
bryanmosley:fix/logs-missing-files

Conversation

@bryanmosley

Copy link
Copy Markdown
Contributor

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update

Motivation and Context

Fixes #2392.

ContainersService.logs(id:) opened stdio.log and vminitd.log eagerly, so either one missing failed the whole request. Both are created by RuntimeLinux at bootstrap, so a container that has never been started has neither. And only RuntimeLinux writes vminitd.log, so with another runtime plugin even plain container logs failed.

A missing log now reads as empty: it's opened as /dev/null, with a debug log line. Any other failure to open a log still throws.

  • /dev/null, not FileHandle.nullDevice. nullDevice has no file descriptor (fileDescriptor is -1). These handles go back to the client over XPC, a -1 dups back as -1, and fileHandles(key:) then returns nil, so container logs would still fail.
  • O_NOFOLLOW on the opens. These are fixed paths that runtimes create as regular files, so a symlink there is never legitimate, and following one would return its target's contents. A symlink fails with ELOOP, so it's refused rather than read as an empty log.
  • The reply still carries two handles, so the client's fhs[0]/fhs[1] indexing is unchanged, and nothing is written into the bundle.

Testing

  • Tested locally
  • Added/updated tests
  • Added/updated docs

Tests/ContainerAPIServiceTests/LogFileTests.swift (7):

  • a missing log is absent and nothing is created;
  • an existing log is read as is;
  • other failures (permissions) still throw;
  • a symlinked log is refused;
  • a dangling symlink is an error, not empty;
  • the stand-in reads as empty;
  • the stand-in survives an XPCMessage round trip while FileHandle.nullDevice doesn't.

swift test --filter ContainerAPIServiceTests passes (17), and make swift-fmt-check is clean.

ContainersService.logs(id:) opened stdio.log and vminitd.log eagerly, so
either one missing failed the whole request. RuntimeLinux creates both when
it bootstraps a container, so one that has never been started has neither,
and only RuntimeLinux writes vminitd.log, so with another runtime plugin even
plain container logs failed.

A missing log now reads as empty, opened as /dev/null with a debug log line;
any other failure to open one still throws. /dev/null rather than
FileHandle.nullDevice, which has no file descriptor: a -1 dups back as -1
over XPC and the client's fileHandles(key:) returns nil. The opens use
O_NOFOLLOW, since these paths are created as regular files and following a
symlink there would return its target's contents.

@abdodarwish995-collab abdodarwish995-collab left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Xxxxxx

@github-actions

Copy link
Copy Markdown

Code Coverage

Tier Line Coverage
Unit 22.27%
Integration 69.41%
Combined 77.48%

@jglogan
jglogan merged commit 86d31db into apple:main Oct 15, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: container logs fails for a container that has never been started, or whose runtime writes no boot log

3 participants