@@ -420,6 +420,7 @@ public final class SwiftDriverJobTaskAction: TaskAction, BuildValueValidatingTas
420
420
private var pid = llbuild_pid_t. invalid
421
421
422
422
var executionError : String ?
423
+ var wasSignaled : Bool = false
423
424
private var processStarted = false
424
425
private var _commandResult : CommandResult ?
425
426
var commandResult : CommandResult ? {
@@ -469,10 +470,15 @@ public final class SwiftDriverJobTaskAction: TaskAction, BuildValueValidatingTas
469
470
}
470
471
471
472
func processFinished( result: CommandExtendedResult ) {
473
+ if wasSignaled {
474
+ // If the process was already signaled, this might be in a reproducer creation. No need to update finish status.
475
+ return
476
+ }
472
477
guard let status = Processes . ExitStatus. init ( rawValue: result. exitStatus) else {
473
478
// nil means the job is stopped or continued. It should not call finished.
474
479
return
475
480
}
481
+ wasSignaled = status. wasSignaled
476
482
// This may be updated by commandStarted in the case of certain failures,
477
483
// so only update the exit status in output delegate if it is nil.
478
484
if outputDelegate. result == nil {
@@ -526,6 +532,21 @@ public final class SwiftDriverJobTaskAction: TaskAction, BuildValueValidatingTas
526
532
527
533
try await spawn( commandLine: options. commandLine, environment: environment, workingDirectory: task. workingDirectory, dynamicExecutionDelegate: dynamicExecutionDelegate, clientDelegate: clientDelegate, processDelegate: delegate)
528
534
535
+ // Generate crash reproducoer.
536
+ if delegate. wasSignaled {
537
+ // The output directory for crash reproducer is:
538
+ // * Specified by environment
539
+ // * Primary output path directory
540
+ // * Temp directory
541
+ let reproDir = environment [ " SWIFT_CRASH_DIAGNOSTICS_DIR " ] . map ( Path . init) ?? driverJob. driverJob. outputs. first? . dirname
542
+ try await withTemporaryDirectory ( dir: reproDir, prefix: " swift-crash-reproducer " , removeTreeOnDeinit: false ) { dir in
543
+ if let reproCommand = try await plannedBuild? . getCrashReproducerCommand ( for: driverJob, output: dir) {
544
+ try await spawn ( commandLine: reproCommand, environment: environment, workingDirectory: task. workingDirectory, dynamicExecutionDelegate: dynamicExecutionDelegate, clientDelegate: clientDelegate, processDelegate: delegate)
545
+ outputDelegate. note ( " Crash reproducer created in \( dir. str) " )
546
+ }
547
+ }
548
+ }
549
+
529
550
if let error = delegate . executionError {
530
551
outputDelegate. error ( error)
531
552
return . failed
0 commit comments