|
10 | 10 | //
|
11 | 11 | //===----------------------------------------------------------------------===//
|
12 | 12 |
|
13 |
| -import Foundation |
| 13 | +package import Foundation |
14 | 14 | import SWBUtil
|
15 | 15 | package import SWBCore
|
16 |
| -package import SWBTaskExecution |
17 | 16 |
|
18 | 17 | #if os(macOS)
|
19 | 18 | import OSLog
|
20 | 19 | #endif
|
21 | 20 |
|
22 |
| -extension TaskOutputDelegate { |
23 |
| - package func emitSandboxingViolations(task: any ExecutableTask, commandResult result: CommandResult) { |
24 |
| - guard task.isSandboxed && result == .failed else { |
25 |
| - return |
26 |
| - } |
27 |
| - |
28 |
| - for message in task.extractSandboxViolationMessages(startTime: startTime) { |
29 |
| - emit(Diagnostic(behavior: .error, location: .unknown, data: DiagnosticData(message))) |
30 |
| - } |
31 |
| - } |
32 |
| -} |
33 |
| - |
34 | 21 | extension ExecutableTask {
|
35 | 22 | /// Whether or not this task is being executed within a sandbox which restricts filesystem access to declared inputs and outputs.
|
36 | 23 | ///
|
37 | 24 | /// - note: Currently this will be true for any task whose executable is `sandbox-exec`, not only tasks which were created using _Swift Builds_ sandboxing mechanism and therefore whose diagnostics contain the message sentinel that we look for. However, this shouldn't really matter in practice at this time as if this property is true for a task not sandboxed _by Swift Build_, we'll simply not extract any diagnostics for it. The only way to get into this situation is to create such tasks in the PIF, which end-users can't do.
|
38 |
| - fileprivate var isSandboxed: Bool { |
| 25 | + package var isSandboxed: Bool { |
39 | 26 | return commandLine.first?.asByteString == ByteString(encodingAsUTF8: "/usr/bin/sandbox-exec")
|
40 | 27 | }
|
41 | 28 |
|
42 |
| - fileprivate func extractSandboxViolationMessages(startTime: Date) -> [String] { |
| 29 | + /// This must be called from threads which aren't Swift async worker threads. This func uses OSLog which kicks off async work and waits for it on a semaphore, causing deadlocks when invoked from Swift Concurrency worker threads. |
| 30 | + @available(*, noasync) |
| 31 | + package func extractSandboxViolationMessages_ASYNC_UNSAFE(startTime: Date) -> [String] { |
43 | 32 | var res: [String] = []
|
44 | 33 | #if os(macOS)
|
| 34 | + withUnsafeCurrentTask { task in |
| 35 | + if task != nil { |
| 36 | + preconditionFailure("This function should not be invoked from the Swift Concurrency thread pool as it may lead to deadlock via thread starvation.") |
| 37 | + } |
| 38 | + } |
| 39 | + |
45 | 40 | if let store = try? OSLogStore.local() {
|
46 | 41 | let query = String("((processID == 0 AND senderImagePath CONTAINS[c] \"/Sandbox\") OR (process == \"sandboxd\" AND subsystem == \"com.apple.sandbox.reporting\")) AND (eventMessage CONTAINS[c] %@)")
|
47 | 42 | let endTime = Date()
|
|
0 commit comments