45
45
46
46
#include " CompilationRecord.h"
47
47
48
+ #include < signal.h>
49
+
48
50
#define DEBUG_TYPE " batch-mode"
49
51
50
52
// Batch-mode has a sub-mode for testing that randomizes batch partitions,
@@ -111,6 +113,7 @@ Compilation::Compilation(DiagnosticEngine &Diags,
111
113
bool EnableIncrementalBuild,
112
114
bool EnableBatchMode,
113
115
unsigned BatchSeed,
116
+ Optional<unsigned > BatchCount,
114
117
bool ForceOneBatchRepartition,
115
118
bool SaveTemps,
116
119
bool ShowDriverTimeCompilation,
@@ -130,6 +133,7 @@ Compilation::Compilation(DiagnosticEngine &Diags,
130
133
OutputCompilationRecordForModuleOnlyBuild),
131
134
EnableBatchMode(EnableBatchMode),
132
135
BatchSeed(BatchSeed),
136
+ BatchCount(BatchCount),
133
137
ForceOneBatchRepartition(ForceOneBatchRepartition),
134
138
SaveTemps(SaveTemps),
135
139
ShowDriverTimeCompilation(ShowDriverTimeCompilation),
@@ -456,6 +460,35 @@ namespace driver {
456
460
}
457
461
}
458
462
463
+ // / Check to see if a job produced a zero-length serialized diagnostics
464
+ // / file, which is used to indicate batch-constituents that were batched
465
+ // / together with a failing constituent but did not, themselves, produce any
466
+ // / errors.
467
+ bool jobWasBatchedWithFailingJobs (const Job *J) const {
468
+ auto DiaPath =
469
+ J->getOutput ().getAnyOutputForType (file_types::TY_SerializedDiagnostics);
470
+ if (DiaPath.empty ())
471
+ return false ;
472
+ if (!llvm::sys::fs::is_regular_file (DiaPath))
473
+ return false ;
474
+ uint64_t Size;
475
+ auto EC = llvm::sys::fs::file_size (DiaPath, Size);
476
+ if (EC)
477
+ return false ;
478
+ return Size == 0 ;
479
+ }
480
+
481
+ // / If a batch-constituent job happens to be batched together with a job
482
+ // / that exits with an error, the batch-constituent may be considered
483
+ // / "cancelled".
484
+ bool jobIsCancelledBatchConstituent (int ReturnCode,
485
+ const Job *ContainerJob,
486
+ const Job *ConstituentJob) {
487
+ return ReturnCode != 0 &&
488
+ isBatchJob (ContainerJob) &&
489
+ jobWasBatchedWithFailingJobs (ConstituentJob);
490
+ }
491
+
459
492
// / Unpack a \c BatchJob that has finished into its constituent \c Job
460
493
// / members, and call \c taskFinished on each, propagating any \c
461
494
// / TaskFinishedResponse other than \c
@@ -481,6 +514,27 @@ namespace driver {
481
514
return res;
482
515
}
483
516
517
+ void
518
+ emitParseableOutputForEachFinishedJob (ProcessId Pid, int ReturnCode,
519
+ StringRef Output,
520
+ const Job *FinishedCmd,
521
+ TaskProcessInformation ProcInfo) {
522
+ FinishedCmd->forEachContainedJobAndPID (Pid, [&](const Job *J,
523
+ Job::PID P) {
524
+ if (jobIsCancelledBatchConstituent (ReturnCode, FinishedCmd, J)) {
525
+ // Simulate SIGINT-interruption to parseable-output consumer for any
526
+ // constituent of a failing batch job that produced no errors of its
527
+ // own.
528
+ parseable_output::emitSignalledMessage (llvm::errs (), *J, P,
529
+ " cancelled batch constituent" ,
530
+ " " , SIGINT, ProcInfo);
531
+ } else {
532
+ parseable_output::emitFinishedMessage (llvm::errs (), *J, P, ReturnCode,
533
+ Output, ProcInfo);
534
+ }
535
+ });
536
+ }
537
+
484
538
// / Callback which will be called immediately after a task has finished
485
539
// / execution. Determines if execution should continue, and also schedule
486
540
// / any additional Jobs which we now know we need to run.
@@ -508,12 +562,8 @@ namespace driver {
508
562
llvm::errs () << Output;
509
563
break ;
510
564
case OutputLevel::Parseable:
511
- // Parseable output was requested.
512
- FinishedCmd->forEachContainedJobAndPID (Pid, [&](const Job *J,
513
- Job::PID P) {
514
- parseable_output::emitFinishedMessage (llvm::errs (), *J, P,
515
- ReturnCode, Output, ProcInfo);
516
- });
565
+ emitParseableOutputForEachFinishedJob (Pid, ReturnCode, Output,
566
+ FinishedCmd, ProcInfo);
517
567
break ;
518
568
}
519
569
}
@@ -880,7 +930,9 @@ namespace driver {
880
930
return ;
881
931
}
882
932
883
- size_t NumPartitions = TQ->getNumberOfParallelTasks ();
933
+ size_t NumPartitions = (Comp.BatchCount .hasValue () ?
934
+ Comp.BatchCount .getValue () :
935
+ TQ->getNumberOfParallelTasks ());
884
936
CommandSetVector Batchable, NonBatchable;
885
937
std::vector<const Job *> Batches;
886
938
bool PretendTheCommandLineIsTooLongOnce =
0 commit comments