Skip to content

Commit 395a981

Browse files
committed
We need to ensure that we terminate (SIGINT) the running compiler processes without emitting an error that those processes got terminated, and allow the driver to continue execution so that it is able to emit parseable-output which communicates that the terminated compiler jobs were interrupted.
Resolves rdar://74527749
1 parent 8f1d770 commit 395a981

File tree

2 files changed

+23
-10
lines changed

2 files changed

+23
-10
lines changed

Sources/SwiftDriverExecution/MultiJobExecutor.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,11 @@ class ExecuteJobRule: LLBuildRule {
539539
}
540540
#if !os(Windows)
541541
case let .signalled(signal):
542-
context.diagnosticsEngine.emit(.error_command_signalled(kind: job.kind, signal: signal))
542+
// An interrupt of an individual compiler job means it was deliberatly cancelled,
543+
// most likely by the driver itself. This does not constitute an error.
544+
if signal != SIGINT {
545+
context.diagnosticsEngine.emit(.error_command_signalled(kind: job.kind, signal: signal))
546+
}
543547
#endif
544548
}
545549
}

Sources/swift-driver/main.swift

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,22 @@ import TSCUtility
1818

1919
var intHandler: InterruptHandler?
2020
let diagnosticsEngine = DiagnosticsEngine(handlers: [Driver.stderrDiagnosticsHandler])
21+
var driverInterrupted = false
22+
func getExitCode(_ code: Int32) -> Int32 {
23+
if driverInterrupted {
24+
return (SIGINT | 0x80)
25+
}
26+
return code
27+
}
2128

2229
do {
30+
2331
let processSet = ProcessSet()
2432
intHandler = try InterruptHandler {
25-
// Ignore the interruption signal.
26-
// The underlying swift compiler isn't ready to be safely interrupted yet and
27-
// interrupting them may cause red-herring build failures that may pollute the build
28-
// log.
29-
diagnosticsEngine.emit(.remark("Compilation process interrupted"))
33+
// Terminate running compiler jobs and let the driver exit gracefully, remembering
34+
// to return a corresponding exit code when done.
35+
processSet.terminate()
36+
driverInterrupted = true
3037
}
3138

3239
if ProcessEnv.vars["SWIFT_ENABLE_EXPLICIT_MODULE"] != nil {
@@ -57,6 +64,7 @@ do {
5764
diagnosticsEngine: diagnosticsEngine,
5865
executor: executor,
5966
integratedDriver: false)
67+
6068
// FIXME: The following check should be at the end of Driver.init, but current
6169
// usage of the DiagnosticVerifier in tests makes this difficult.
6270
guard !driver.diagnosticEngine.hasErrors else { throw Diagnostics.fatalError }
@@ -65,14 +73,15 @@ do {
6573
try driver.run(jobs: jobs)
6674

6775
if driver.diagnosticEngine.hasErrors {
68-
exit(EXIT_FAILURE)
76+
exit(getExitCode(EXIT_FAILURE))
6977
}
78+
exit(getExitCode(0))
7079
} catch Diagnostics.fatalError {
71-
exit(EXIT_FAILURE)
80+
exit(getExitCode(EXIT_FAILURE))
7281
} catch let diagnosticData as DiagnosticData {
7382
diagnosticsEngine.emit(.error(diagnosticData))
74-
exit(EXIT_FAILURE)
83+
exit(getExitCode(EXIT_FAILURE))
7584
} catch {
7685
print("error: \(error)")
77-
exit(EXIT_FAILURE)
86+
exit(getExitCode(EXIT_FAILURE))
7887
}

0 commit comments

Comments
 (0)