Repository navigation
[stdlib] Make stdin/stdout/stderr Sendable on all platforms - #89891
Conversation
|
@swift-ci test |
|
@swift-ci test android |
|
Thanks for triggering those @finagolfin I'll take a look at the failures |
7992176 to
4417408
Compare
|
@kateinoigakukun, @3405691582, and @al45tair, please take a look @swift-ci test |
|
@swift-ci test android |
|
I made the wrappers optional in my latest push because the first iteration of this change broke swift-log's usage of stderr and I (maybe incorrectly) thought that I should be able to achieve my goal without breaking existing usages. After the latest builds, I'm a bit confused.
#elseif canImport(Glibc)
let systemStderr = Glibc.stderr!
let systemStdout = Glibc.stdout!
#elseif canImport(Musl)
let systemStderr = Musl.stderr!
let systemStdout = Musl.stdout!
#elseif canImport(WASILibc)
let systemStderr = WASILibc.stderr!
let systemStdout = WASILibc.stdout!But the backtrace utils use stdout and stderr without force unwrapping (source). I think what this means is that the original return type of the |
weissi
left a comment
There was a problem hiding this comment.
thanks, this looks good to me.
4417408 to
2217c8a
Compare
In Swift 6 mode these were diagnosed as shared mutable global state (swiftlang#75601). Mark them nonisolated(unsafe) across the libc overlays. Glibc/Musl/Android/WASI define them as computed vars backed by the _swift_stdlib_std* shims; Platform.swift covers OpenBSD, FreeBSD/PS4, and Windows. They are OpaquePointer where FILE is opaque (Musl, WASI, Android, OpenBSD) and UnsafeMutablePointer<FILE> elsewhere. Adds the StdioSendable regression test.
2217c8a to
73fee33
Compare
|
@finagolfin Could you trigger the tests again on the latest changes? |
|
Hold on, Windows CI may be broken, will try in an hour or so if it isn't. |
|
@kateinoigakukun and @al45tair, would be good to get your sign-off here, plus from any of @swiftlang/android-workgroup who have input. |
|
Windows CI should be good now. @swift-ci smoke test |
|
@swift-ci test android |
|
Anything else needed from me to merge? |
|
Just waiting to see if anyone else has input, think you've done your part. @ktoso, wdyt? |
|
You'll need to rebase, some merge conflict. |
ktoso
left a comment
There was a problem hiding this comment.
Long overdue, thanks for the PR! Looks good to me and enough other folks chimed in as well
|
I took a stab at resolving the conflict, kicking off CI and we can merge if it passes. |
|
@swift-ci please test |
swift-backtrace was using `setvbuf(stdout, nil, _IOLBF, 0)` which failed under `x86_64-swift-linux-musl` which broke after the recent changes in swiftlang#89891 We need to match the way those funcs are imported, so those variables must be `UnsafeMutablePointer<FILE>!` Also adds a test actually using those globals so we won't regress randomly. Resolves rdar://182172802
swift-backtrace was using `setvbuf(stdout, nil, _IOLBF, 0)` which failed under `x86_64-swift-linux-musl` which broke after the recent changes in swiftlang#89891 We need to match the way those funcs are imported, so those variables must be `UnsafeMutablePointer<FILE>!` Also adds a test actually using those globals so we won't regress randomly. Resolves rdar://182172802
swift-backtrace was using `setvbuf(stdout, nil, _IOLBF, 0)` which failed under `x86_64-swift-linux-musl` which broke after the recent changes in #89891 We need to match the way those funcs are imported, so those variables must be `UnsafeMutablePointer<FILE>!` Also adds a test actually using those globals so we won't regress randomly. Resolves rdar://182172802
swift-backtrace was using `setvbuf(stdout, nil, _IOLBF, 0)` which failed under `x86_64-swift-linux-musl` after the recent changes in #89891. Musl's <stdio.h> forward-declares `struct _IO_FILE`, so Clang imports FILE as a nominal Swift type and every stdio function in the same overlay takes `UnsafeMutablePointer<FILE>`. Match that signature. Android (bionic) and WASI don't expose FILE as a Swift-nameable type at all, so their stdio functions come in typed with OpaquePointer. Keep those two overlays as OpaquePointer (initial fix attempt got that wrong -- flagged by finagolfin during review, ref swift-inspect String+Extensions.swift for the recommended `typealias File = OpaquePointer` bridging pattern under `#if os(Android)`). Also extends test/stdlib/StdioSendable.swift to actually pass the globals to stdio functions on the platforms where FILE is nominal (guards Android/WASI out). Resolves rdar://182172802
swift-backtrace was using `setvbuf(stdout, nil, _IOLBF, 0)` which failed under `x86_64-swift-linux-musl` after the recent changes in #89891 We need to match the way those funcs are imported, so those variables must be `UnsafeMutablePointer<FILE>!` Also adds a test actually using those globals so we won't regress randomly. Resolves rdar://182172802
…ssue/PR 90679) swift-backtrace was using `setvbuf(stdout, nil, _IOLBF, 0)` which failed under `x86_64-swift-linux-musl` after the recent changes in swiftlang/swift#89891 We need to match the way those funcs are imported, so those variables must be `UnsafeMutablePointer<FILE>!` Also adds a test actually using those globals so we won't regress randomly. Resolves rdar://182172802
) swift-backtrace was using `setvbuf(stdout, nil, _IOLBF, 0)` which failed under `x86_64-swift-linux-musl` after the recent changes in swiftlang#89891 We need to match the way those funcs are imported, so those variables must be `UnsafeMutablePointer<FILE>!` Also adds a test actually using those globals so we won't regress randomly. Resolves rdar://182172802
Recent pulls swiftlang#89891 and swiftlang#90679 tried to improve the async typing for Musl but broke the static linux SDK CI, so temporarily reverting.
```
$ echo "@preconcurrency import var Foundation.stderr" | swiftly run +main-snapshot-2026-08-11 swiftc - -o /dev/null
<stdin>:1:28: error: ambiguous name 'stderr' in module 'Foundation'
1 | @preconcurrency import var Foundation.stderr
| `- error: ambiguous name 'stderr' in module 'Foundation'
2 |
Glibc.stderr:1:32: note: found this candidate
1 | nonisolated(unsafe) public var stderr: UnsafeMutablePointer<FILE>! { get }
| `- note: found this candidate
/usr/include/stdio.h:151:14: note: found this candidate
149 | extern FILE *stdin; /* Standard input stream. */
150 | extern FILE *stdout; /* Standard output stream. */
151 | extern FILE *stderr; /* Standard error output stream. */
| `- note: found this candidate
152 | /* C89/C99 say they're macros. Make them happy. */
153 | #define stdin stdin
```
swiftlang/swift#89891
```
$ echo "@preconcurrency import var Foundation.stderr" | swiftly run +main-snapshot-2026-08-11 swiftc - -o /dev/null
<stdin>:1:28: error: ambiguous name 'stderr' in module 'Foundation'
1 | @preconcurrency import var Foundation.stderr
| `- error: ambiguous name 'stderr' in module 'Foundation'
2 |
Glibc.stderr:1:32: note: found this candidate
1 | nonisolated(unsafe) public var stderr: UnsafeMutablePointer<FILE>! { get }
| `- note: found this candidate
/usr/include/stdio.h:151:14: note: found this candidate
149 | extern FILE *stdin; /* Standard input stream. */
150 | extern FILE *stdout; /* Standard output stream. */
151 | extern FILE *stderr; /* Standard error output stream. */
| `- note: found this candidate
152 | /* C89/C99 say they're macros. Make them happy. */
153 | #define stdin stdin
```
swiftlang/swift#89891
…807) * PackageToJS: Derive WASI and shared memory support from wasm imports The SwiftBuild backend's build directory doesn't encode the target triple, so detect the traits derived from it by parsing the imports of the product binary instead. The imports are now parsed as a part of the packaging build graph. * Avoid `import var Foundation.stderr` ``` $ echo "@preconcurrency import var Foundation.stderr" | swiftly run +main-snapshot-2026-08-11 swiftc - -o /dev/null <stdin>:1:28: error: ambiguous name 'stderr' in module 'Foundation' 1 | @preconcurrency import var Foundation.stderr | `- error: ambiguous name 'stderr' in module 'Foundation' 2 | Glibc.stderr:1:32: note: found this candidate 1 | nonisolated(unsafe) public var stderr: UnsafeMutablePointer<FILE>! { get } | `- note: found this candidate /usr/include/stdio.h:151:14: note: found this candidate 149 | extern FILE *stdin; /* Standard input stream. */ 150 | extern FILE *stdout; /* Standard output stream. */ 151 | extern FILE *stderr; /* Standard error output stream. */ | `- note: found this candidate 152 | /* C89/C99 say they're macros. Make them happy. */ 153 | #define stdin stdin ``` swiftlang/swift#89891 * CI: Install Swift toolchain preserving its usr/bin layout Flattening the tarball into /usr/local makes SwiftPM derive a bogus toolchain root, so the swiftbuild build system cannot find swiftc. * PackageToJS: Record every import kind while parsing wasm imports Only memory imports were collected, so `WasmFeatures.isWASI` never saw `wasi_snapshot_preview1` and the generated node.js dropped the WASI import while still constructing a WASI instance. * PackageToJS: run per-target test runners under the swiftbuild build system `swift package js test` assumed the native build system's single combined `<Package>PackageTests` binary: it looked for one `.wasm`/`.xctest` under `.build/<config>/`, packaged it, and ran it. SwiftBuild produces no combined test binary. It emits one `<TestTarget>-test-runner.wasm` per test target under `.build/out/Products/`, plus an aggregate target that only orchestrates building them, so the old lookup failed with "Failed to find 'JavaScriptKitPackageTests.wasm'". (cherry picked from commit c12c7e9) * Install the JS event loop executor in async test targets Because SwiftBuild mode produces a linked executable for each test target. (cherry picked from commit 0a1f926) * BridgeJS: Skip type handle registration for unlinked modules `js test` generates the glue from every test target's skeletons, but the SwiftBuild build system links one binary per test target, so the eager registration hit a missing export. * PackageToJS: Share the linked JS modules with the aggregated glue The per-runner `bridge-js.js` copied to the base output directory for test preludes imports its JavaScript modules relative to itself, so copy the `bridge-js-modules` directory next to it. * BridgeJS: Require the imports object for static-only imported types An imported type looked up from `getImports` contributes its static methods too, but only a constructor marked the imports object as needed, so the glue referenced an undeclared `imports`. * PackageToJS: Generate each test bundle's glue from what its binary links in `js test` generated the glue from every test target's skeletons and handed the same copy to each SwiftBuild per-target runner, which described exports those binaries don't have. Package the aggregated glue once into the shared base directory, where preludes import it by a fixed path, and give each runner glue scoped to the target it links in. This supersedes the registration guard in the JS code generator.
Resolves #75601.
Extends the existing OpenBSD shim functions in LibcOverlayShims.h to cover Linux and WASI, and re-exports them as nonisolated(unsafe) computed vars in the Glibc, Musl, Android, and WASILibc overlays.