diff --git a/.changes/refactor-ios-stdout-stderr.md b/.changes/refactor-ios-stdout-stderr.md new file mode 100644 index 000000000..766cd9fb5 --- /dev/null +++ b/.changes/refactor-ios-stdout-stderr.md @@ -0,0 +1,6 @@ +--- +"tauri": patch:bug +"tauri-macros": patch:bug +--- + +Fix iOS deadlock when running on the simulator from Xcode by properly piping stdout/stderr messages through the Xcode console and OSLog. diff --git a/crates/tauri/mobile/ios-api/Sources/Tauri/Logger.swift b/crates/tauri/mobile/ios-api/Sources/Tauri/Logger.swift index 9fa6e3fe7..d055090dc 100644 --- a/crates/tauri/mobile/ios-api/Sources/Tauri/Logger.swift +++ b/crates/tauri/mobile/ios-api/Sources/Tauri/Logger.swift @@ -4,6 +4,86 @@ import os.log import UIKit +import Foundation + +class StdoutRedirector { + private var originalStdout: Int32 = -1 + private var originalStderr: Int32 = -1 + private var stdoutPipe: [Int32] = [-1, -1] + private var stderrPipe: [Int32] = [-1, -1] + private var stdoutReadSource: DispatchSourceRead? + private var stderrReadSource: DispatchSourceRead? + + func start() { + originalStdout = dup(STDOUT_FILENO) + originalStderr = dup(STDERR_FILENO) + + guard Darwin.pipe(&stdoutPipe) == 0, + Darwin.pipe(&stderrPipe) == 0 else { + Logger.error("Failed to create stdout/stderr pipes") + return + } + + dup2(stdoutPipe[1], STDOUT_FILENO) + dup2(stderrPipe[1], STDERR_FILENO) + close(stdoutPipe[1]) + close(stderrPipe[1]) + + stdoutReadSource = createReader( + readPipe: stdoutPipe[0], + writeToOriginal: originalStdout, + label: "stdout" + ) + + stderrReadSource = createReader( + readPipe: stderrPipe[0], + writeToOriginal: originalStderr, + label: "stderr" + ) + } + + private func createReader( + readPipe: Int32, + writeToOriginal: Int32, + label: String + ) -> DispatchSourceRead { + let source = DispatchSource.makeReadSource( + fileDescriptor: readPipe, + queue: .global(qos: .utility) + ) + + source.setEventHandler { + let bufferSize = 4096 + var buffer = [UInt8](repeating: 0, count: bufferSize) + let bytesRead = read(readPipe, &buffer, bufferSize) + + if bytesRead > 0 { + let output = String( + bytes: buffer[0..