Skip to content

Commit 6ec69b7

Browse files
authored
Merge pull request #17167 from graydon/rdar-40526328-emit-SIGINT-for-cancelled-batch-constituents
2 parents e97fde0 + dcc4373 commit 6ec69b7

File tree

5 files changed

+99
-20
lines changed

5 files changed

+99
-20
lines changed

include/swift/Driver/Compilation.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ class Compilation {
174174
/// Provides a randomization seed to batch-mode partitioning, for debugging.
175175
const unsigned BatchSeed;
176176

177+
/// Overrides parallelism level as count of batches, if in batch-mode.
178+
const Optional<unsigned> BatchCount;
179+
177180
/// In order to test repartitioning, set to true if
178181
/// -driver-force-one-batch-repartition is present.
179182
const bool ForceOneBatchRepartition = false;
@@ -228,6 +231,7 @@ class Compilation {
228231
bool EnableIncrementalBuild = false,
229232
bool EnableBatchMode = false,
230233
unsigned BatchSeed = 0,
234+
Optional<unsigned> BatchCount = None,
231235
bool ForceOneBatchRepartition = false,
232236
bool SaveTemps = false,
233237
bool ShowDriverTimeCompilation = false,

include/swift/Driver/Driver.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,6 @@ class Driver {
176176
/// Indicates whether the driver should check that the input files exist.
177177
bool CheckInputFilesExist = true;
178178

179-
/// Provides a randomization seed to batch-mode partitioning, for debugging.
180-
unsigned DriverBatchSeed = 0;
181-
182-
/// Forces a repartition for testing.
183-
bool DriverForceOneBatchRepartition = false;
184-
185179
public:
186180
Driver(StringRef DriverExecutable, StringRef Name,
187181
ArrayRef<const char *> Args, DiagnosticEngine &Diags);

include/swift/Option/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ def driver_filelist_threshold_EQ : Joined<["-"], "driver-filelist-threshold=">,
110110
def driver_batch_seed : Separate<["-"], "driver-batch-seed">,
111111
InternalDebugOpt,
112112
HelpText<"Use the given seed value to randomize batch-mode partitions">;
113+
def driver_batch_count : Separate<["-"], "driver-batch-count">,
114+
InternalDebugOpt,
115+
HelpText<"Use the given number of batch-mode partitions, rather than default parallelism level">;
113116
def driver_force_one_batch_repartition : Flag<["-"], "driver-force-one-batch-repartition">,
114117
InternalDebugOpt,
115118
HelpText<"Force one batch repartitioning for testing">;

lib/Driver/Compilation.cpp

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545

4646
#include "CompilationRecord.h"
4747

48+
#include <signal.h>
49+
4850
#define DEBUG_TYPE "batch-mode"
4951

5052
// Batch-mode has a sub-mode for testing that randomizes batch partitions,
@@ -111,6 +113,7 @@ Compilation::Compilation(DiagnosticEngine &Diags,
111113
bool EnableIncrementalBuild,
112114
bool EnableBatchMode,
113115
unsigned BatchSeed,
116+
Optional<unsigned> BatchCount,
114117
bool ForceOneBatchRepartition,
115118
bool SaveTemps,
116119
bool ShowDriverTimeCompilation,
@@ -130,6 +133,7 @@ Compilation::Compilation(DiagnosticEngine &Diags,
130133
OutputCompilationRecordForModuleOnlyBuild),
131134
EnableBatchMode(EnableBatchMode),
132135
BatchSeed(BatchSeed),
136+
BatchCount(BatchCount),
133137
ForceOneBatchRepartition(ForceOneBatchRepartition),
134138
SaveTemps(SaveTemps),
135139
ShowDriverTimeCompilation(ShowDriverTimeCompilation),
@@ -456,6 +460,35 @@ namespace driver {
456460
}
457461
}
458462

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+
459492
/// Unpack a \c BatchJob that has finished into its constituent \c Job
460493
/// members, and call \c taskFinished on each, propagating any \c
461494
/// TaskFinishedResponse other than \c
@@ -481,6 +514,27 @@ namespace driver {
481514
return res;
482515
}
483516

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+
484538
/// Callback which will be called immediately after a task has finished
485539
/// execution. Determines if execution should continue, and also schedule
486540
/// any additional Jobs which we now know we need to run.
@@ -508,12 +562,8 @@ namespace driver {
508562
llvm::errs() << Output;
509563
break;
510564
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);
517567
break;
518568
}
519569
}
@@ -880,7 +930,9 @@ namespace driver {
880930
return;
881931
}
882932

883-
size_t NumPartitions = TQ->getNumberOfParallelTasks();
933+
size_t NumPartitions = (Comp.BatchCount.hasValue() ?
934+
Comp.BatchCount.getValue() :
935+
TQ->getNumberOfParallelTasks());
884936
CommandSetVector Batchable, NonBatchable;
885937
std::vector<const Job *> Batches;
886938
bool PretendTheCommandLineIsTooLongOnce =

lib/Driver/Driver.cpp

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,35 @@ static bool getFilelistThreshold(DerivedArgList &Args, size_t &FilelistThreshold
643643
return false;
644644
}
645645

646+
static unsigned
647+
getDriverBatchSeed(llvm::opt::InputArgList &ArgList,
648+
DiagnosticEngine &Diags) {
649+
unsigned DriverBatchSeed = 0;
650+
if (const Arg *A = ArgList.getLastArg(options::OPT_driver_batch_seed)) {
651+
if (StringRef(A->getValue()).getAsInteger(10, DriverBatchSeed)) {
652+
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
653+
A->getAsString(ArgList), A->getValue());
654+
}
655+
}
656+
return DriverBatchSeed;
657+
}
658+
659+
static Optional<unsigned>
660+
getDriverBatchCount(llvm::opt::InputArgList &ArgList,
661+
DiagnosticEngine &Diags)
662+
{
663+
if (const Arg *A = ArgList.getLastArg(options::OPT_driver_batch_count)) {
664+
unsigned Count = 0;
665+
if (StringRef(A->getValue()).getAsInteger(10, Count)) {
666+
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
667+
A->getAsString(ArgList), A->getValue());
668+
} else {
669+
return Count;
670+
}
671+
}
672+
return None;
673+
}
674+
646675
std::unique_ptr<Compilation>
647676
Driver::buildCompilation(const ToolChain &TC,
648677
std::unique_ptr<llvm::opt::InputArgList> ArgList) {
@@ -663,13 +692,9 @@ Driver::buildCompilation(const ToolChain &TC,
663692
ArgList->hasArg(options::OPT_driver_show_incremental);
664693
bool ShowJobLifecycle =
665694
ArgList->hasArg(options::OPT_driver_show_job_lifecycle);
666-
if (const Arg *A = ArgList->getLastArg(options::OPT_driver_batch_seed)) {
667-
if (StringRef(A->getValue()).getAsInteger(10, DriverBatchSeed)) {
668-
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
669-
A->getAsString(*ArgList), A->getValue());
670-
}
671-
}
672-
DriverForceOneBatchRepartition =
695+
unsigned DriverBatchSeed = getDriverBatchSeed(*ArgList, Diags);
696+
Optional<unsigned> DriverBatchCount = getDriverBatchCount(*ArgList, Diags);
697+
bool DriverForceOneBatchRepartition =
673698
ArgList->hasArg(options::OPT_driver_force_one_batch_repartition);
674699

675700
bool Incremental = ArgList->hasArg(options::OPT_incremental);
@@ -837,6 +862,7 @@ Driver::buildCompilation(const ToolChain &TC,
837862
Incremental,
838863
BatchMode,
839864
DriverBatchSeed,
865+
DriverBatchCount,
840866
DriverForceOneBatchRepartition,
841867
SaveTemps,
842868
ShowDriverTimeCompilation,

0 commit comments

Comments
 (0)