Skip to content

Fix Linux build: replace fputs(_:stderr) with FileHandle.standardError - #441

Merged
leogdion merged 1 commit into
v1.0.0-beta.4from
mistdemo-linux-stderr
Aug 28, 2026
Merged

Fix Linux build: replace fputs(_:stderr) with FileHandle.standardError#441
leogdion merged 1 commit into
v1.0.0-beta.4from
mistdemo-linux-stderr

Conversation

@leogdion

@leogdionleogdion commented Aug 28, 2026

Copy link
Copy Markdown
Member

The error

The Examples workflow's Test MistDemo on Ubuntu job fails to compile:

Examples/MistDemo/Sources/MistDemo/MistDemo.swift:44:33: error: reference to var 'stderr'
is not concurrency-safe because it involves shared mutable state
44 | fputs("❌ \(message)\n", stderr)
| `- error

Why it is Linux-only

glibc declares the stream as extern FILE *stderr — a plain mutable global — which Swift imports as a global var. Under Swift 6 strict concurrency, referencing a non-Sendable, non-isolated mutable global is an error.

Darwin's headers expose stderr differently (via __stderrp), and the Darwin overlay imports it in a form the concurrency checker accepts, so the exact same line compiles cleanly on macOS. That's why this got through review and the macOS jobs: it cannot reproduce locally on a Mac.

The line was introduced in #429 (0b6bea9).

The fix

One-line change in Examples/MistDemo/Sources/MistDemo/MistDemo.swift: write through FileHandle instead of the C stream.

// Glibc exposes `stderr` as a mutable global, which Swift 6 strict
// concurrency rejects; FileHandle keeps this portable to Linux.
FileHandle.standardError.write(Data("\(message)\n".utf8))

This is the idiom already used everywhere else in this codebase for stderr output — MistDemoConfig+DatabaseConfiguration.swift, LookupCommand.swift, LookupAllRecordsCommand.swift, ModifyCommand.swift, ModifyZonesCommand.swift, DiscoverAllUserIdentitiesCommand.swift, and BushelCloudKit's ConsoleOutput — so the fix matches existing style rather than introducing a new pattern. internal import Foundation was already present in the file, so no import change was needed (the repo's explicit-access-modifier import convention is preserved).

I grepped all of Examples/ and Sources/ for stderr/stdout: this was the only code reference. Every other hit is a doc comment or a test asserting on help text, none of which touch the C globals. No other changes are included in this PR.

Verification

CheckResult
swift build in Examples/MistDemo (macOS, Swift 6.3)pass
swift test in Examples/MistDemo (macOS)pass — 994 tests / 295 suites, 1 known issue
swift build + swift test at repo root (macOS)pass — 618 tests / 195 suites
swiftlint --strict + swift-format lint --strict on the changed fileclean
Linuxswift builddocker run --rm swift:6.3 in Examples/MistDemo (same image the CI job uses)pass — "Build complete!", the error is gone
Linuxswift test — same containerpass — 994 tests / 295 suites, 1 known issue (matches the macOS run)

Linux verification was actually performed, not assumed: the pre-fix error reproduces only on Linux, and the swift:6.3 container build now completes with exit code 0.

Note on LINT_MODE=STRICT ./Scripts/lint.sh: it reports 54 pre-existing violations on this base branch (file-name, type-contents-order, line-length, etc. across Sources/, Tests/, and Scripts/OpenAPITools/Package.swift). None are in the file this PR touches, and the count is unchanged by this PR — Scripts/lint.sh doesn't even scan Examples/. Worth flagging separately: when $CI is unset, lint.sh runs swift-format --in-place and swiftlint --fix regardless of LINT_MODE, so running it locally rewrites unrelated files (and the locally-resolved swift-format disagrees with the pinned one). That's out of scope here.

🤖 Generated with Claude Code

glibc declares `stderr` as `extern FILE *stderr` — a mutable global — so
Swift 6 strict concurrency rejects any reference to it:
MistDemo.swift:44:33: error: reference to var 'stderr' is not
concurrency-safe because it involves shared mutable state
Darwin's `stderr` is imported differently, so this only breaks the
"Test MistDemo on Ubuntu" job in the Examples workflow; the macOS build
is unaffected. The call was introduced in #429 (0b6bea9).
Switch to `FileHandle.standardError.write(Data(...utf8))`, the idiom
already used across MistDemoKit (LookupCommand, ModifyCommand,
ModifyZonesCommand, MistDemoConfig+DatabaseConfiguration, …) and
BushelCloudKit's ConsoleOutput. `internal import Foundation` was already
present. No other file under Examples/ or Sources/ references `stderr`
or `stdout` in code (remaining hits are doc comments and a test string).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xs1c8vvxjCxqZiStcmuPS2
@coderabbitai

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 36e055b3-d1c4-4ad2-a631-5a39b8a84f0d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecovBot commented Aug 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.39%. Comparing base (61235b5) to head (ef84566).

Additional details and impacted files
@@ Coverage Diff @@## v1.0.0-beta.4 #441 +/- ##
=================================================
- Coverage 81.45% 81.39% -0.07% 
=================================================
Files 191 191 Lines 4719 4719 =================================================
- Hits 3844 3841 -3 - Misses 875 878 +3 
FlagCoverage Δ
mistdemo-spm-macos11.31% <ø> (ø)
mistdemo-swift-6.2-jammy11.31% <ø> (?)
mistdemo-swift-6.2-noble11.31% <ø> (?)
mistdemo-swift-6.3-jammy11.31% <ø> (?)
mistdemo-swift-6.3-noble11.31% <ø> (?)
mistdemo-swift-6.4-jammy11.31% <ø> (?)
mistdemo-swift-6.4-noble11.31% <ø> (?)
spm80.01% <ø> (+0.02%)⬆️
swift-6.1-jammy80.11% <ø> (-0.15%)⬇️
swift-6.1-noble80.13% <ø> (-0.07%)⬇️
swift-6.2-jammy80.01% <ø> (-0.32%)⬇️
swift-6.2-noble80.13% <ø> (+0.14%)⬆️
swift-6.3-jammy80.16% <ø> (+0.14%)⬆️
swift-6.3-noble79.97% <ø> (-0.07%)⬇️
swift-6.4-jammy80.01% <ø> (-0.24%)⬇️
swift-6.4-noble80.13% <ø> (-0.03%)⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@leogdion
leogdion merged commit 7018ff1 into v1.0.0-beta.4Aug 28, 2026
83 of 84 checks passed
@leogdion
leogdion deleted the mistdemo-linux-stderr branch August 29, 2026 12:05
Sign up for freeto 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.

1 participant

@leogdion