Skip to content

Commit 5dbed2e

Browse files
authored
Merge pull request #506 from artemcm/SIGINTExperiment
Interrupt handler: terminate (SIGINT) running compiler processes and allow the driver to exit gracefully.
2 parents fb9a032 + 395a981 commit 5dbed2e

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)