From 4f02fb601e218d7142cdcecf2ed30851ac43f7b4 Mon Sep 17 00:00:00 2001 From: phranck Date: Fri, 30 Jan 2026 17:04:43 +0100 Subject: [PATCH] fix: Use @preconcurrency import for Glibc/Musl to resolve stdout concurrency error The previous nonisolated(unsafe) approach failed because the concurrency check triggers on the read of stdout itself, not on the local binding. @preconcurrency import suppresses all concurrency diagnostics for the imported module, which is the correct fix for C library globals that Swift 6 cannot reason about. --- Sources/TUIKit/Rendering/Terminal.swift | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/Sources/TUIKit/Rendering/Terminal.swift b/Sources/TUIKit/Rendering/Terminal.swift index 6a9cb2f..13e83c8 100644 --- a/Sources/TUIKit/Rendering/Terminal.swift +++ b/Sources/TUIKit/Rendering/Terminal.swift @@ -8,9 +8,9 @@ import Foundation #if canImport(Glibc) - import Glibc + @preconcurrency import Glibc #elseif canImport(Musl) - import Musl + @preconcurrency import Musl #elseif canImport(Darwin) import Darwin #endif @@ -144,23 +144,12 @@ public final class Terminal: @unchecked Sendable { // MARK: - Output - /// Flushes the standard output stream. - /// - /// On Linux (Glibc/Musl), `stdout` is a shared mutable global. - /// Swift 6 strict concurrency flags direct access as unsafe. - /// `nonisolated(unsafe)` suppresses the diagnostic — this is safe - /// because `fflush` is called single-threaded from the main loop. - private func flushStdout() { - nonisolated(unsafe) let stdoutHandle = stdout - fflush(stdoutHandle) - } - /// Writes a string to the terminal. /// /// - Parameter string: The string to write. public func write(_ string: String) { print(string, terminator: "") - flushStdout() + fflush(stdout) } /// Writes a string and moves to a new line. @@ -168,7 +157,7 @@ public final class Terminal: @unchecked Sendable { /// - Parameter string: The string to write. public func writeLine(_ string: String = "") { print(string) - flushStdout() + fflush(stdout) } /// Clears the screen and moves cursor to position (1,1).