Skip to content

Commit 942cb08

Browse files
committed
Implement frontend parseable-output batch job quasi-PID assignment.
Starting at a crude -1000, each invocation primary input will get its own unique quasi-Pid. Invocations with only one primary (non-batch) will get a real OS Pid. The selection of the constant starting point matches what the driver does when outputting its parseable output.
1 parent 23e374c commit 942cb08

File tree

6 files changed

+66
-35
lines changed

6 files changed

+66
-35
lines changed

include/swift/Basic/ParseableOutput.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,23 @@ namespace swift {
2727

2828
namespace parseable_output {
2929

30+
/// Quasi-PIDs are _negative_ PID-like unique keys used to
31+
/// masquerade batch job constituents as (quasi)processes, when writing
32+
/// parseable output to consumers that don't understand the idea of a batch
33+
/// job. They are negative in order to avoid possibly colliding with real
34+
/// PIDs (which are always positive). We start at -1000 here as a crude but
35+
/// harmless hedge against colliding with an errno value that might slip
36+
/// into the stream of real PIDs (say, due to a TaskQueue bug).
37+
const int QUASI_PID_START = -1000;
38+
3039
/// Emits a "began" message to the given stream, corresponding to a Driver Job.
3140
void emitBeganMessage(raw_ostream &os, const driver::Job &Cmd, int64_t Pid,
3241
sys::TaskProcessInformation ProcInfo);
3342

3443
/// Emits a "began" message to the given stream, corresponding to a given
3544
/// Frontend Compiler Invocation.
3645
void emitBeganMessage(raw_ostream &os, const CompilerInvocation &Invocation,
37-
ArrayRef<const char *> Args, int64_t Pid,
38-
sys::TaskProcessInformation ProcInfo);
46+
ArrayRef<const char *> Args, int64_t OSPid);
3947

4048
/// Emits a "finished" message to the given stream.
4149
void emitFinishedMessage(raw_ostream &os, const driver::Job &Cmd, int64_t Pid,
@@ -45,10 +53,9 @@ void emitFinishedMessage(raw_ostream &os, const driver::Job &Cmd, int64_t Pid,
4553
/// Emits a "finished" message to the given stream corresponding to a given
4654
/// Frontend Compiler Invocation.
4755
void emitFinishedMessage(
48-
raw_ostream &os, const CompilerInvocation &Invocation, int64_t Pid,
49-
int ExitStatus,
56+
raw_ostream &os, const CompilerInvocation &Invocation, int ExitStatus,
5057
const llvm::StringMap<std::vector<std::string>> &FileSpecificDiagnostics,
51-
sys::TaskProcessInformation ProcInfo);
58+
int64_t OSPid);
5259

5360
/// Emits a "signalled" message to the given stream.
5461
void emitSignalledMessage(raw_ostream &os, const driver::Job &Cmd, int64_t Pid,

include/swift/Frontend/FrontendInputsAndOutputs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ class FrontendInputsAndOutputs {
110110
bool
111111
forEachPrimaryInput(llvm::function_ref<bool(const InputFile &)> fn) const;
112112

113+
/// Iterates over primary inputs, exposing their unique ordered index
114+
/// If \p fn returns true, exit early and return true.
115+
bool forEachPrimaryInputWithIndex(
116+
llvm::function_ref<bool(const InputFile &, unsigned index)> fn) const;
117+
113118
/// If \p fn returns true, exit early and return true.
114119
bool
115120
forEachNonPrimaryInput(llvm::function_ref<bool(const InputFile &)> fn) const;

lib/Basic/ParseableOutput.cpp

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -420,11 +420,18 @@ void parseable_output::emitBeganMessage(raw_ostream &os, const driver::Job &Cmd,
420420
void parseable_output::emitBeganMessage(raw_ostream &os,
421421
const CompilerInvocation &Invocation,
422422
ArrayRef<const char *> Args,
423-
int64_t Pid,
424-
TaskProcessInformation ProcInfo) {
423+
int64_t OSPid) {
425424
const auto &IO = Invocation.getFrontendOptions().InputsAndOutputs;
426-
IO.forEachPrimaryInput([&](const InputFile &Input) -> bool {
427-
BeganInvocationMessage msg(Invocation, Input, Args, Pid, ProcInfo);
425+
const auto ProcInfo = sys::TaskProcessInformation(OSPid);
426+
427+
// Parseable output clients may not understand the idea of a batch
428+
// compilation. We assign each primary in a batch job a quasi process id,
429+
// making sure it cannot collide with a real PID (always positive). Non-batch
430+
// compilation gets a real OS PID.
431+
int64_t Pid = IO.hasUniquePrimaryInput() ? OSPid : QUASI_PID_START;
432+
IO.forEachPrimaryInputWithIndex([&](const InputFile &Input,
433+
unsigned idx) -> bool {
434+
BeganInvocationMessage msg(Invocation, Input, Args, Pid - idx, ProcInfo);
428435
emitMessage(os, msg);
429436
return false;
430437
});
@@ -439,27 +446,33 @@ void parseable_output::emitFinishedMessage(raw_ostream &os,
439446
}
440447

441448
void parseable_output::emitFinishedMessage(
442-
raw_ostream &os, const CompilerInvocation &Invocation, int64_t Pid,
443-
int ExitStatus,
449+
raw_ostream &os, const CompilerInvocation &Invocation, int ExitStatus,
444450
const llvm::StringMap<std::vector<std::string>> &FileSpecificDiagnostics,
445-
TaskProcessInformation ProcInfo) {
451+
int64_t OSPid) {
446452
const auto &IO = Invocation.getFrontendOptions().InputsAndOutputs;
447-
IO.forEachPrimaryInput([&](const InputFile &Input) -> bool {
448-
assert(FileSpecificDiagnostics.count(Input.getFileName()) != 0 &&
449-
"Expected diagnostic collection for input.");
450-
451-
// Join all diagnostics produced for this file into a single output.
452-
auto PrimaryDiags = FileSpecificDiagnostics.lookup(Input.getFileName());
453-
const char* const Delim = "\n";
454-
std::ostringstream JoinedDiags;
455-
std::copy(PrimaryDiags.begin(), PrimaryDiags.end(),
456-
std::ostream_iterator<std::string>(JoinedDiags, Delim));
457-
FinishedInvocationMessage msg(Invocation, Pid,
458-
JoinedDiags.str(),
459-
ExitStatus, ProcInfo);
460-
emitMessage(os, msg);
461-
return false;
462-
});
453+
const auto ProcInfo = sys::TaskProcessInformation(OSPid);
454+
455+
// Parseable output clients may not understand the idea of a batch
456+
// compilation. We assign each primary in a batch job a quasi process id,
457+
// making sure it cannot collide with a real PID (always positive). Non-batch
458+
// compilation gets a real OS PID.
459+
int64_t Pid = IO.hasUniquePrimaryInput() ? OSPid : QUASI_PID_START;
460+
IO.forEachPrimaryInputWithIndex(
461+
[&](const InputFile &Input, unsigned idx) -> bool {
462+
assert(FileSpecificDiagnostics.count(Input.getFileName()) != 0 &&
463+
"Expected diagnostic collection for input.");
464+
465+
// Join all diagnostics produced for this file into a single output.
466+
auto PrimaryDiags = FileSpecificDiagnostics.lookup(Input.getFileName());
467+
const char *const Delim = "\n";
468+
std::ostringstream JoinedDiags;
469+
std::copy(PrimaryDiags.begin(), PrimaryDiags.end(),
470+
std::ostream_iterator<std::string>(JoinedDiags, Delim));
471+
FinishedInvocationMessage msg(Invocation, Pid - idx, JoinedDiags.str(),
472+
ExitStatus, ProcInfo);
473+
emitMessage(os, msg);
474+
return false;
475+
});
463476
}
464477

465478
void parseable_output::emitSignalledMessage(

lib/Driver/Compilation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ namespace driver {
204204
/// PIDs (which are always positive). We start at -1000 here as a crude but
205205
/// harmless hedge against colliding with an errno value that might slip
206206
/// into the stream of real PIDs (say, due to a TaskQueue bug).
207-
int64_t NextBatchQuasiPID = -1000;
207+
int64_t NextBatchQuasiPID = parseable_output::QUASI_PID_START;
208208

209209
/// All jobs which have finished execution or which have been determined
210210
/// that they don't need to run.

lib/Frontend/FrontendInputsAndOutputs.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,14 @@ bool FrontendInputsAndOutputs::forEachPrimaryInput(
101101
return false;
102102
}
103103

104+
bool FrontendInputsAndOutputs::forEachPrimaryInputWithIndex(
105+
llvm::function_ref<bool(const InputFile &, unsigned index)> fn) const {
106+
for (unsigned i : PrimaryInputsInOrder)
107+
if (fn(AllInputs[i], i))
108+
return true;
109+
return false;
110+
}
111+
104112
bool FrontendInputsAndOutputs::forEachNonPrimaryInput(
105113
llvm::function_ref<bool(const InputFile &)> fn) const {
106114
return forEachInput([&](const InputFile &f) -> bool {

lib/FrontendTool/FrontendTool.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,9 +2073,8 @@ int swift::performFrontend(ArrayRef<const char *> Args,
20732073
}
20742074

20752075
if (Invocation.getFrontendOptions().FrontendParseableOutput) {
2076-
parseable_output::emitBeganMessage(
2077-
llvm::errs(), Invocation, Args, llvm::sys::ProcessInfo::InvalidPid,
2078-
sys::TaskProcessInformation(getpid()));
2076+
parseable_output::emitBeganMessage(llvm::errs(), Invocation, Args,
2077+
getpid());
20792078
}
20802079

20812080
int ReturnValue = 0;
@@ -2097,9 +2096,8 @@ int swift::performFrontend(ArrayRef<const char *> Args,
20972096
StatsReporter->noteCurrentProcessExitStatus(r);
20982097

20992098
if (Invocation.getFrontendOptions().FrontendParseableOutput) {
2100-
parseable_output::emitFinishedMessage(
2101-
llvm::errs(), Invocation, llvm::sys::ProcessInfo::InvalidPid, r,
2102-
FileSpecificDiagnostics, sys::TaskProcessInformation(getpid()));
2099+
parseable_output::emitFinishedMessage(llvm::errs(), Invocation, r,
2100+
FileSpecificDiagnostics, getpid());
21032101
}
21042102

21052103
return r;

0 commit comments

Comments
 (0)