From 19f9c4e0950e5b82b705d78b1e99c5b20ea17a71 Mon Sep 17 00:00:00 2001 From: Robert Connell Date: Wed, 6 Aug 2025 15:44:19 -0400 Subject: [PATCH 1/2] Frequent crashes in LLBuildProgressTracker while building swift-java on linux and swift 6.1.2 --- Sources/Build/LLBuildProgressTracker.swift | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Sources/Build/LLBuildProgressTracker.swift b/Sources/Build/LLBuildProgressTracker.swift index 5f883b0597b..8875bdd736e 100644 --- a/Sources/Build/LLBuildProgressTracker.swift +++ b/Sources/Build/LLBuildProgressTracker.swift @@ -345,12 +345,15 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut // FIXME: This should really happen at the command-level and is just a stopgap measure. let shouldFilterOutput = !self.logLevel.isVerbose && command.verboseDescription.hasPrefix("codesign ") && result .result != .failed + + let commandName = command.name + self.queue.async { - if let buffer = self.nonSwiftMessageBuffers[command.name], !shouldFilterOutput { + if let buffer = self.nonSwiftMessageBuffers[commandName], !shouldFilterOutput { self.progressAnimation.clear() self.outputStream.send(buffer) self.outputStream.flush() - self.nonSwiftMessageBuffers[command.name] = nil + self.nonSwiftMessageBuffers[commandName] = nil } } @@ -362,13 +365,13 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut // The command failed, so we queue up an asynchronous task to see if we have any error messages from the // target to provide advice about. self.queue.async { - guard let target = self.swiftParsers[command.name]?.targetName else { return } + guard let target = self.swiftParsers[commandName]?.targetName else { return } guard let errorMessages = self.errorMessagesByTarget[target] else { return } for errorMessage in errorMessages { // Emit any advice that's provided for each error message. if let adviceMessage = self.buildExecutionContext.buildErrorAdviceProvider?.provideBuildErrorAdvice( for: target, - command: command.name, + command: commandName, message: errorMessage ) { self.outputStream.send("note: \(adviceMessage)\n") From 0d67db77831624c89666a3d19c68e98d2090e9ff Mon Sep 17 00:00:00 2001 From: Robert Connell Date: Thu, 7 Aug 2025 20:50:40 -0400 Subject: [PATCH 2/2] Additiona fixes for command.name and command.description being used after they have been reclaimed. --- Sources/Build/LLBuildProgressTracker.swift | 25 ++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Sources/Build/LLBuildProgressTracker.swift b/Sources/Build/LLBuildProgressTracker.swift index 8875bdd736e..63a6a6caace 100644 --- a/Sources/Build/LLBuildProgressTracker.swift +++ b/Sources/Build/LLBuildProgressTracker.swift @@ -279,6 +279,9 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut guard command.shouldShowStatus else { return } guard !self.swiftParsers.keys.contains(command.name) else { return } + let commandName = command.name + let commandDescription = command.description + self.queue.async { if result == .cancelled { self.cancelled = true @@ -288,8 +291,8 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut self.delegate?.buildSystem(self.buildSystem, didFinishCommand: BuildSystemCommand(command)) if !self.logLevel.isVerbose && !self.logLevel.isQuiet { - let targetName = self.swiftParsers[command.name]?.targetName - self.taskTracker.commandFinished(command, result: result, targetName: targetName) + let targetName = self.swiftParsers[commandName]?.targetName + self.taskTracker.commandFinished(commandDescription, result: result, targetName: targetName) self.updateProgress() } } @@ -539,8 +542,8 @@ private struct CommandTaskTracker { } } - mutating func commandFinished(_ command: SPMLLBuild.Command, result: CommandResult, targetName: String?) { - let progressTextValue = self.progressText(of: command, targetName: targetName) + mutating func commandFinished(_ commandDescription: String, result: CommandResult, targetName: String?) { + let progressTextValue = self.progressText(of: commandDescription, targetName: targetName) self.onTaskProgressUpdateText?(progressTextValue, targetName) self.latestFinishedText = progressTextValue @@ -567,19 +570,19 @@ private struct CommandTaskTracker { } } - private func progressText(of command: SPMLLBuild.Command, targetName: String?) -> String { + private func progressText(of commandDescription: String, targetName: String?) -> String { #if os(Windows) let pathSep: Character = "\\" #else let pathSep: Character = "/" #endif // Transforms descriptions like "Linking ./.build/x86_64-apple-macosx/debug/foo" into "Linking foo". - if let firstSpaceIndex = command.description.firstIndex(of: " "), - let lastDirectorySeparatorIndex = command.description.lastIndex(of: pathSep) + if let firstSpaceIndex = commandDescription.firstIndex(of: " "), + let lastDirectorySeparatorIndex = commandDescription.lastIndex(of: pathSep) { - let action = command.description[..