mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Optionally separate Tasks` stderr from stdout.
Fixes a serious problem where spurious output from xcrun breaks swift's discovery of libarclite. <rdar://problem/28573949>
This commit is contained in:
@@ -72,12 +72,15 @@ public:
|
|||||||
/// \param ReturnCode the return code of the task which finished execution.
|
/// \param ReturnCode the return code of the task which finished execution.
|
||||||
/// \param Output the output from the task which finished execution,
|
/// \param Output the output from the task which finished execution,
|
||||||
/// if available. (This may not be available on all platforms.)
|
/// if available. (This may not be available on all platforms.)
|
||||||
|
/// \param Errors the errors from the task which finished execution, if
|
||||||
|
/// available and SeparateErrors was true. (This may not be available on all
|
||||||
|
/// platforms.)
|
||||||
/// \param Context the context which was passed when the task was added
|
/// \param Context the context which was passed when the task was added
|
||||||
///
|
///
|
||||||
/// \returns true if further execution of tasks should stop,
|
/// \returns true if further execution of tasks should stop,
|
||||||
/// false if execution should continue
|
/// false if execution should continue
|
||||||
typedef std::function<TaskFinishedResponse(ProcessId Pid, int ReturnCode,
|
typedef std::function<TaskFinishedResponse(ProcessId Pid, int ReturnCode,
|
||||||
StringRef Output, void *Context)>
|
StringRef Output, StringRef Errors, void *Context)>
|
||||||
TaskFinishedCallback;
|
TaskFinishedCallback;
|
||||||
|
|
||||||
/// \brief A callback which will be executed if a task exited abnormally due
|
/// \brief A callback which will be executed if a task exited abnormally due
|
||||||
@@ -88,12 +91,15 @@ public:
|
|||||||
/// no reason could be deduced, this may be empty.
|
/// no reason could be deduced, this may be empty.
|
||||||
/// \param Output the output from the task which exited abnormally, if
|
/// \param Output the output from the task which exited abnormally, if
|
||||||
/// available. (This may not be available on all platforms.)
|
/// available. (This may not be available on all platforms.)
|
||||||
|
/// \param Errors the errors from the task which exited abnormally, if
|
||||||
|
/// available and SeparateErrors was true. (This may not be available on all
|
||||||
|
/// platforms.)
|
||||||
/// \param Context the context which was passed when the task was added
|
/// \param Context the context which was passed when the task was added
|
||||||
///
|
///
|
||||||
/// \returns a TaskFinishedResponse indicating whether or not execution
|
/// \returns a TaskFinishedResponse indicating whether or not execution
|
||||||
/// should proceed
|
/// should proceed
|
||||||
typedef std::function<TaskFinishedResponse(ProcessId Pid, StringRef ErrorMsg,
|
typedef std::function<TaskFinishedResponse(ProcessId Pid, StringRef ErrorMsg,
|
||||||
StringRef Output, void *Context)>
|
StringRef Output, StringRef Errors, void *Context)>
|
||||||
TaskSignalledCallback;
|
TaskSignalledCallback;
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
@@ -120,9 +126,10 @@ public:
|
|||||||
/// \param Env the environment which should be used for the task;
|
/// \param Env the environment which should be used for the task;
|
||||||
/// must be null-terminated. If empty, inherits the parent's environment.
|
/// must be null-terminated. If empty, inherits the parent's environment.
|
||||||
/// \param Context an optional context which will be associated with the task
|
/// \param Context an optional context which will be associated with the task
|
||||||
|
/// \param SeparateErrors Controls whether error output is reported separately
|
||||||
virtual void addTask(const char *ExecPath, ArrayRef<const char *> Args,
|
virtual void addTask(const char *ExecPath, ArrayRef<const char *> Args,
|
||||||
ArrayRef<const char *> Env = llvm::None,
|
ArrayRef<const char *> Env = llvm::None,
|
||||||
void *Context = nullptr);
|
void *Context = nullptr, bool SeparateErrors = false);
|
||||||
|
|
||||||
/// \brief Synchronously executes the tasks in the TaskQueue.
|
/// \brief Synchronously executes the tasks in the TaskQueue.
|
||||||
///
|
///
|
||||||
@@ -153,10 +160,13 @@ class DummyTaskQueue : public TaskQueue {
|
|||||||
ArrayRef<const char *> Args;
|
ArrayRef<const char *> Args;
|
||||||
ArrayRef<const char *> Env;
|
ArrayRef<const char *> Env;
|
||||||
void *Context;
|
void *Context;
|
||||||
|
bool SeparateErrors;
|
||||||
|
|
||||||
DummyTask(const char *ExecPath, ArrayRef<const char *> Args,
|
DummyTask(const char *ExecPath, ArrayRef<const char *> Args,
|
||||||
ArrayRef<const char *> Env = llvm::None, void *Context = nullptr)
|
ArrayRef<const char *> Env = llvm::None, void *Context = nullptr,
|
||||||
: ExecPath(ExecPath), Args(Args), Env(Env), Context(Context) {}
|
bool SeparateErrors = false)
|
||||||
|
: ExecPath(ExecPath), Args(Args), Env(Env), Context(Context),
|
||||||
|
SeparateErrors(SeparateErrors) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::queue<std::unique_ptr<DummyTask>> QueuedTasks;
|
std::queue<std::unique_ptr<DummyTask>> QueuedTasks;
|
||||||
@@ -168,7 +178,7 @@ public:
|
|||||||
|
|
||||||
virtual void addTask(const char *ExecPath, ArrayRef<const char *> Args,
|
virtual void addTask(const char *ExecPath, ArrayRef<const char *> Args,
|
||||||
ArrayRef<const char *> Env = llvm::None,
|
ArrayRef<const char *> Env = llvm::None,
|
||||||
void *Context = nullptr);
|
void *Context = nullptr, bool SeparateErrors = false);
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
execute(TaskBeganCallback Began = TaskBeganCallback(),
|
execute(TaskBeganCallback Began = TaskBeganCallback(),
|
||||||
|
|||||||
@@ -112,8 +112,8 @@ bool TaskQueue::execute(TaskBeganCallback Began, TaskFinishedCallback Finished,
|
|||||||
// Wait() returning a return code of -2 indicates the process received
|
// Wait() returning a return code of -2 indicates the process received
|
||||||
// a signal during execution.
|
// a signal during execution.
|
||||||
if (Signalled) {
|
if (Signalled) {
|
||||||
TaskFinishedResponse Response = Signalled(PI.Pid, ErrMsg, StringRef(),
|
TaskFinishedResponse Response =
|
||||||
T->Context);
|
Signalled(PI.Pid, ErrMsg, StringRef(), StringRef(), T->Context);
|
||||||
ContinueExecution = Response != TaskFinishedResponse::StopExecution;
|
ContinueExecution = Response != TaskFinishedResponse::StopExecution;
|
||||||
} else {
|
} else {
|
||||||
// If we don't have a Signalled callback, unconditionally stop.
|
// If we don't have a Signalled callback, unconditionally stop.
|
||||||
@@ -124,7 +124,7 @@ bool TaskQueue::execute(TaskBeganCallback Began, TaskFinishedCallback Finished,
|
|||||||
// finished.
|
// finished.
|
||||||
if (Finished) {
|
if (Finished) {
|
||||||
TaskFinishedResponse Response = Finished(PI.Pid, PI.ReturnCode,
|
TaskFinishedResponse Response = Finished(PI.Pid, PI.ReturnCode,
|
||||||
StringRef(), T->Context);
|
StringRef(), StringRef(), T->Context);
|
||||||
ContinueExecution = Response != TaskFinishedResponse::StopExecution;
|
ContinueExecution = Response != TaskFinishedResponse::StopExecution;
|
||||||
} else if (PI.ReturnCode != 0) {
|
} else if (PI.ReturnCode != 0) {
|
||||||
ContinueExecution = false;
|
ContinueExecution = false;
|
||||||
|
|||||||
@@ -42,9 +42,10 @@ DummyTaskQueue::DummyTaskQueue(unsigned NumberOfParallelTasks)
|
|||||||
DummyTaskQueue::~DummyTaskQueue() = default;
|
DummyTaskQueue::~DummyTaskQueue() = default;
|
||||||
|
|
||||||
void DummyTaskQueue::addTask(const char *ExecPath, ArrayRef<const char *> Args,
|
void DummyTaskQueue::addTask(const char *ExecPath, ArrayRef<const char *> Args,
|
||||||
ArrayRef<const char *> Env, void *Context) {
|
ArrayRef<const char *> Env, void *Context,
|
||||||
QueuedTasks.emplace(
|
bool SeparateErrors) {
|
||||||
std::unique_ptr<DummyTask>(new DummyTask(ExecPath, Args, Env, Context)));
|
QueuedTasks.emplace(std::unique_ptr<DummyTask>(
|
||||||
|
new DummyTask(ExecPath, Args, Env, Context, SeparateErrors)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DummyTaskQueue::execute(TaskQueue::TaskBeganCallback Began,
|
bool DummyTaskQueue::execute(TaskQueue::TaskBeganCallback Began,
|
||||||
@@ -80,7 +81,9 @@ bool DummyTaskQueue::execute(TaskQueue::TaskBeganCallback Began,
|
|||||||
|
|
||||||
if (Finished) {
|
if (Finished) {
|
||||||
std::string Output = "Output placeholder\n";
|
std::string Output = "Output placeholder\n";
|
||||||
if (Finished(P.first, 0, Output, P.second->Context) ==
|
std::string Errors =
|
||||||
|
P.second->SeparateErrors ? "Error placeholder\n" : "";
|
||||||
|
if (Finished(P.first, 0, Output, Errors, P.second->Context) ==
|
||||||
TaskFinishedResponse::StopExecution)
|
TaskFinishedResponse::StopExecution)
|
||||||
SubtaskFailed = true;
|
SubtaskFailed = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,12 +58,18 @@ class Task {
|
|||||||
/// Context which should be associated with this task.
|
/// Context which should be associated with this task.
|
||||||
void *Context;
|
void *Context;
|
||||||
|
|
||||||
|
/// True if the errors of the Task should be stored in Errors instead of Output.
|
||||||
|
bool SeparateErrors;
|
||||||
|
|
||||||
/// The pid of this Task when executing.
|
/// The pid of this Task when executing.
|
||||||
pid_t Pid;
|
pid_t Pid;
|
||||||
|
|
||||||
/// A pipe for reading output from the child process.
|
/// A pipe for reading output from the child process.
|
||||||
int Pipe;
|
int Pipe;
|
||||||
|
|
||||||
|
/// A pipe for reading errors from the child prcess, if SeparateErrors is true.
|
||||||
|
int ErrorPipe;
|
||||||
|
|
||||||
/// The current state of the Task.
|
/// The current state of the Task.
|
||||||
enum {
|
enum {
|
||||||
Preparing,
|
Preparing,
|
||||||
@@ -74,11 +80,16 @@ class Task {
|
|||||||
/// Once the Task has finished, this contains the buffered output of the Task.
|
/// Once the Task has finished, this contains the buffered output of the Task.
|
||||||
std::string Output;
|
std::string Output;
|
||||||
|
|
||||||
|
/// Once the Task has finished, if SeparateErrors is true, this contains the errors
|
||||||
|
/// from the Task.
|
||||||
|
std::string Errors;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Task(const char *ExecPath, ArrayRef<const char *> Args,
|
Task(const char *ExecPath, ArrayRef<const char *> Args,
|
||||||
ArrayRef<const char *> Env, void *Context)
|
ArrayRef<const char *> Env, void *Context, bool SeparateErrors)
|
||||||
: ExecPath(ExecPath), Args(Args), Env(Env), Context(Context),
|
: ExecPath(ExecPath), Args(Args), Env(Env), Context(Context),
|
||||||
Pid(-1), Pipe(-1), State(Preparing) {
|
SeparateErrors(SeparateErrors), Pid(-1), Pipe(-1), ErrorPipe(-1),
|
||||||
|
State(Preparing) {
|
||||||
assert((Env.empty() || Env.back() == nullptr) &&
|
assert((Env.empty() || Env.back() == nullptr) &&
|
||||||
"Env must either be empty or null-terminated!");
|
"Env must either be empty or null-terminated!");
|
||||||
}
|
}
|
||||||
@@ -86,17 +97,19 @@ public:
|
|||||||
const char *getExecPath() const { return ExecPath; }
|
const char *getExecPath() const { return ExecPath; }
|
||||||
ArrayRef<const char *> getArgs() const { return Args; }
|
ArrayRef<const char *> getArgs() const { return Args; }
|
||||||
StringRef getOutput() const { return Output; }
|
StringRef getOutput() const { return Output; }
|
||||||
|
StringRef getErrors() const { return Errors; }
|
||||||
void *getContext() const { return Context; }
|
void *getContext() const { return Context; }
|
||||||
pid_t getPid() const { return Pid; }
|
pid_t getPid() const { return Pid; }
|
||||||
int getPipe() const { return Pipe; }
|
int getPipe() const { return Pipe; }
|
||||||
|
int getErrorPipe() const { return ErrorPipe; }
|
||||||
|
|
||||||
/// \brief Begins execution of this Task.
|
/// \brief Begins execution of this Task.
|
||||||
/// \returns true on error, false on success
|
/// \returns true on error, false on success
|
||||||
bool execute();
|
bool execute();
|
||||||
|
|
||||||
/// \brief Reads data from the pipe, if any is available.
|
/// \brief Reads data from the pipes, if any is available.
|
||||||
/// \returns true on error, false on success
|
/// \returns true on error, false on success
|
||||||
bool readFromPipe();
|
bool readFromPipes();
|
||||||
|
|
||||||
/// \brief Performs any post-execution work for this Task, such as reading
|
/// \brief Performs any post-execution work for this Task, such as reading
|
||||||
/// piped output and closing the pipe.
|
/// piped output and closing the pipe.
|
||||||
@@ -121,6 +134,12 @@ bool Task::execute() {
|
|||||||
pipe(FullPipe);
|
pipe(FullPipe);
|
||||||
Pipe = FullPipe[0];
|
Pipe = FullPipe[0];
|
||||||
|
|
||||||
|
int FullErrorPipe[2];
|
||||||
|
if (SeparateErrors) {
|
||||||
|
pipe(FullErrorPipe);
|
||||||
|
ErrorPipe = FullErrorPipe[0];
|
||||||
|
}
|
||||||
|
|
||||||
// Get the environment to pass down to the subtask.
|
// Get the environment to pass down to the subtask.
|
||||||
const char *const *envp = Env.empty() ? nullptr : Env.data();
|
const char *const *envp = Env.empty() ? nullptr : Env.data();
|
||||||
if (!envp) {
|
if (!envp) {
|
||||||
@@ -138,8 +157,19 @@ bool Task::execute() {
|
|||||||
posix_spawn_file_actions_init(&FileActions);
|
posix_spawn_file_actions_init(&FileActions);
|
||||||
|
|
||||||
posix_spawn_file_actions_adddup2(&FileActions, FullPipe[1], STDOUT_FILENO);
|
posix_spawn_file_actions_adddup2(&FileActions, FullPipe[1], STDOUT_FILENO);
|
||||||
posix_spawn_file_actions_adddup2(&FileActions, STDOUT_FILENO, STDERR_FILENO);
|
|
||||||
|
if (SeparateErrors) {
|
||||||
|
posix_spawn_file_actions_adddup2(&FileActions, FullErrorPipe[1],
|
||||||
|
STDERR_FILENO);
|
||||||
|
} else {
|
||||||
|
posix_spawn_file_actions_adddup2(&FileActions, STDOUT_FILENO,
|
||||||
|
STDERR_FILENO);
|
||||||
|
}
|
||||||
|
|
||||||
posix_spawn_file_actions_addclose(&FileActions, FullPipe[0]);
|
posix_spawn_file_actions_addclose(&FileActions, FullPipe[0]);
|
||||||
|
if (SeparateErrors) {
|
||||||
|
posix_spawn_file_actions_addclose(&FileActions, FullErrorPipe[0]);
|
||||||
|
}
|
||||||
|
|
||||||
// Spawn the subtask.
|
// Spawn the subtask.
|
||||||
int spawnErr = posix_spawn(&Pid, ExecPath, &FileActions, nullptr,
|
int spawnErr = posix_spawn(&Pid, ExecPath, &FileActions, nullptr,
|
||||||
@@ -148,9 +178,15 @@ bool Task::execute() {
|
|||||||
|
|
||||||
posix_spawn_file_actions_destroy(&FileActions);
|
posix_spawn_file_actions_destroy(&FileActions);
|
||||||
close(FullPipe[1]);
|
close(FullPipe[1]);
|
||||||
|
if (SeparateErrors) {
|
||||||
|
close(FullErrorPipe[1]);
|
||||||
|
}
|
||||||
|
|
||||||
if (spawnErr != 0 || Pid == 0) {
|
if (spawnErr != 0 || Pid == 0) {
|
||||||
close(FullPipe[0]);
|
close(FullPipe[0]);
|
||||||
|
if (SeparateErrors) {
|
||||||
|
close(FullErrorPipe[0]);
|
||||||
|
}
|
||||||
State = Finished;
|
State = Finished;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -159,6 +195,9 @@ bool Task::execute() {
|
|||||||
switch (Pid) {
|
switch (Pid) {
|
||||||
case -1: {
|
case -1: {
|
||||||
close(FullPipe[0]);
|
close(FullPipe[0]);
|
||||||
|
if (SeparateErrors) {
|
||||||
|
close(FullErrorPipe[0]);
|
||||||
|
}
|
||||||
State = Finished;
|
State = Finished;
|
||||||
Pid = 0;
|
Pid = 0;
|
||||||
break;
|
break;
|
||||||
@@ -166,8 +205,15 @@ bool Task::execute() {
|
|||||||
case 0: {
|
case 0: {
|
||||||
// Child process: Execute the program.
|
// Child process: Execute the program.
|
||||||
dup2(FullPipe[1], STDOUT_FILENO);
|
dup2(FullPipe[1], STDOUT_FILENO);
|
||||||
|
if (SeparateErrors) {
|
||||||
|
dup2(FullErrorPipe[1], STDERR_FILENO);
|
||||||
|
} else {
|
||||||
dup2(STDOUT_FILENO, STDERR_FILENO);
|
dup2(STDOUT_FILENO, STDERR_FILENO);
|
||||||
|
}
|
||||||
close(FullPipe[0]);
|
close(FullPipe[0]);
|
||||||
|
if (SeparateErrors) {
|
||||||
|
close(FullErrorPipe[0]);
|
||||||
|
}
|
||||||
execve(ExecPath, const_cast<char **>(argvp), const_cast<char **>(envp));
|
execve(ExecPath, const_cast<char **>(argvp), const_cast<char **>(envp));
|
||||||
|
|
||||||
// If the execve() failed, we should exit. Follow Unix protocol and
|
// If the execve() failed, we should exit. Follow Unix protocol and
|
||||||
@@ -184,6 +230,9 @@ bool Task::execute() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
close(FullPipe[1]);
|
close(FullPipe[1]);
|
||||||
|
if (SeparateErrors) {
|
||||||
|
close(FullErrorPipe[1]);
|
||||||
|
}
|
||||||
|
|
||||||
if (Pid == 0)
|
if (Pid == 0)
|
||||||
return true;
|
return true;
|
||||||
@@ -192,7 +241,7 @@ bool Task::execute() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Task::readFromPipe() {
|
static bool readFromAPipe(int Pipe, std::string &Output) {
|
||||||
char outputBuffer[1024];
|
char outputBuffer[1024];
|
||||||
ssize_t readBytes = 0;
|
ssize_t readBytes = 0;
|
||||||
while ((readBytes = read(Pipe, outputBuffer, sizeof(outputBuffer))) != 0) {
|
while ((readBytes = read(Pipe, outputBuffer, sizeof(outputBuffer))) != 0) {
|
||||||
@@ -209,6 +258,14 @@ bool Task::readFromPipe() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Task::readFromPipes() {
|
||||||
|
bool Ret = readFromAPipe(Pipe, Output);
|
||||||
|
if (SeparateErrors) {
|
||||||
|
Ret |= readFromAPipe(ErrorPipe, Errors);
|
||||||
|
}
|
||||||
|
return Ret;
|
||||||
|
}
|
||||||
|
|
||||||
void Task::finishExecution() {
|
void Task::finishExecution() {
|
||||||
assert(State == Executing &&
|
assert(State == Executing &&
|
||||||
"This Task must be executing to finish execution!");
|
"This Task must be executing to finish execution!");
|
||||||
@@ -216,9 +273,12 @@ void Task::finishExecution() {
|
|||||||
State = Finished;
|
State = Finished;
|
||||||
|
|
||||||
// Read the output of the command, so we can use it later.
|
// Read the output of the command, so we can use it later.
|
||||||
readFromPipe();
|
readFromPipes();
|
||||||
|
|
||||||
close(Pipe);
|
close(Pipe);
|
||||||
|
if (SeparateErrors) {
|
||||||
|
close(ErrorPipe);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TaskQueue::supportsBufferingOutput() {
|
bool TaskQueue::supportsBufferingOutput() {
|
||||||
@@ -239,8 +299,10 @@ unsigned TaskQueue::getNumberOfParallelTasks() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TaskQueue::addTask(const char *ExecPath, ArrayRef<const char *> Args,
|
void TaskQueue::addTask(const char *ExecPath, ArrayRef<const char *> Args,
|
||||||
ArrayRef<const char *> Env, void *Context) {
|
ArrayRef<const char *> Env, void *Context,
|
||||||
std::unique_ptr<Task> T(new Task(ExecPath, Args, Env, Context));
|
bool SeparateErrors) {
|
||||||
|
std::unique_ptr<Task> T(
|
||||||
|
new Task(ExecPath, Args, Env, Context, SeparateErrors));
|
||||||
QueuedTasks.push(std::move(T));
|
QueuedTasks.push(std::move(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,6 +341,8 @@ bool TaskQueue::execute(TaskBeganCallback Began, TaskFinishedCallback Finished,
|
|||||||
}
|
}
|
||||||
|
|
||||||
PollFds.push_back({ T->getPipe(), POLLIN | POLLPRI | POLLHUP, 0 });
|
PollFds.push_back({ T->getPipe(), POLLIN | POLLPRI | POLLHUP, 0 });
|
||||||
|
// We should also poll T->getErrorPipe(), but this intrroduces timing
|
||||||
|
// issues with shutting down the task after reading getPipe().
|
||||||
ExecutingTasks[Pid] = std::move(T);
|
ExecutingTasks[Pid] = std::move(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,7 +374,7 @@ bool TaskQueue::execute(TaskBeganCallback Began, TaskFinishedCallback Finished,
|
|||||||
Task &T = *iter->second;
|
Task &T = *iter->second;
|
||||||
if (fd.revents & POLLIN || fd.revents & POLLPRI) {
|
if (fd.revents & POLLIN || fd.revents & POLLPRI) {
|
||||||
// There's data available to read.
|
// There's data available to read.
|
||||||
T.readFromPipe();
|
T.readFromPipes();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd.revents & POLLHUP || fd.revents & POLLERR) {
|
if (fd.revents & POLLHUP || fd.revents & POLLERR) {
|
||||||
@@ -339,7 +403,7 @@ bool TaskQueue::execute(TaskBeganCallback Began, TaskFinishedCallback Finished,
|
|||||||
// If we have a TaskFinishedCallback, only set SubtaskFailed to
|
// If we have a TaskFinishedCallback, only set SubtaskFailed to
|
||||||
// true if the callback returns StopExecution.
|
// true if the callback returns StopExecution.
|
||||||
SubtaskFailed = Finished(T.getPid(), Result, T.getOutput(),
|
SubtaskFailed = Finished(T.getPid(), Result, T.getOutput(),
|
||||||
T.getContext()) ==
|
T.getErrors(), T.getContext()) ==
|
||||||
TaskFinishedResponse::StopExecution;
|
TaskFinishedResponse::StopExecution;
|
||||||
} else if (Result != 0) {
|
} else if (Result != 0) {
|
||||||
// Since we don't have a TaskFinishedCallback, treat a subtask
|
// Since we don't have a TaskFinishedCallback, treat a subtask
|
||||||
@@ -353,8 +417,8 @@ bool TaskQueue::execute(TaskBeganCallback Began, TaskFinishedCallback Finished,
|
|||||||
StringRef ErrorMsg = strsignal(Signal);
|
StringRef ErrorMsg = strsignal(Signal);
|
||||||
|
|
||||||
if (Signalled) {
|
if (Signalled) {
|
||||||
TaskFinishedResponse Response = Signalled(T.getPid(), ErrorMsg,
|
TaskFinishedResponse Response =
|
||||||
T.getOutput(),
|
Signalled(T.getPid(), ErrorMsg, T.getOutput(), T.getErrors(),
|
||||||
T.getContext());
|
T.getContext());
|
||||||
if (Response == TaskFinishedResponse::StopExecution)
|
if (Response == TaskFinishedResponse::StopExecution)
|
||||||
// If we have a TaskCrashedCallback, only set SubtaskFailed to
|
// If we have a TaskCrashedCallback, only set SubtaskFailed to
|
||||||
|
|||||||
@@ -482,6 +482,7 @@ int Compilation::performJobsImpl() {
|
|||||||
// it should also schedule any additional commands which we now know need
|
// it should also schedule any additional commands which we now know need
|
||||||
// to run.
|
// to run.
|
||||||
auto taskFinished = [&](ProcessId Pid, int ReturnCode, StringRef Output,
|
auto taskFinished = [&](ProcessId Pid, int ReturnCode, StringRef Output,
|
||||||
|
StringRef Errors,
|
||||||
void *Context) -> TaskFinishedResponse {
|
void *Context) -> TaskFinishedResponse {
|
||||||
const Job *FinishedCmd = (const Job *)Context;
|
const Job *FinishedCmd = (const Job *)Context;
|
||||||
|
|
||||||
@@ -613,6 +614,7 @@ int Compilation::performJobsImpl() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
auto taskSignalled = [&](ProcessId Pid, StringRef ErrorMsg, StringRef Output,
|
auto taskSignalled = [&](ProcessId Pid, StringRef ErrorMsg, StringRef Output,
|
||||||
|
StringRef Errors,
|
||||||
void *Context) -> TaskFinishedResponse {
|
void *Context) -> TaskFinishedResponse {
|
||||||
const Job *SignalledCmd = (const Job *)Context;
|
const Job *SignalledCmd = (const Job *)Context;
|
||||||
|
|
||||||
|
|||||||
@@ -1204,6 +1204,7 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,
|
|||||||
[&OI](sys::ProcessId PID,
|
[&OI](sys::ProcessId PID,
|
||||||
int returnCode,
|
int returnCode,
|
||||||
StringRef output,
|
StringRef output,
|
||||||
|
StringRef errors,
|
||||||
void *unused) -> sys::TaskFinishedResponse {
|
void *unused) -> sys::TaskFinishedResponse {
|
||||||
if (returnCode == 0) {
|
if (returnCode == 0) {
|
||||||
output = output.rtrim();
|
output = output.rtrim();
|
||||||
|
|||||||
@@ -787,11 +787,11 @@ static bool findXcodeClangPath(llvm::SmallVectorImpl<char> &path) {
|
|||||||
if (!xcrunPath.getError()) {
|
if (!xcrunPath.getError()) {
|
||||||
const char *args[] = {"-f", "clang", nullptr};
|
const char *args[] = {"-f", "clang", nullptr};
|
||||||
sys::TaskQueue queue;
|
sys::TaskQueue queue;
|
||||||
queue.addTask(xcrunPath->c_str(), args);
|
queue.addTask(xcrunPath->c_str(), args, /*Env=*/llvm::None,
|
||||||
queue.execute(nullptr,
|
/*Context=*/nullptr,
|
||||||
[&path](sys::ProcessId PID,
|
/*SeparateErrors=*/true);
|
||||||
int returnCode,
|
queue.execute(nullptr, [&path](sys::ProcessId PID, int returnCode,
|
||||||
StringRef output,
|
StringRef output, StringRef errors,
|
||||||
void *unused) -> sys::TaskFinishedResponse {
|
void *unused) -> sys::TaskFinishedResponse {
|
||||||
if (returnCode == 0) {
|
if (returnCode == 0) {
|
||||||
output = output.rtrim();
|
output = output.rtrim();
|
||||||
|
|||||||
Reference in New Issue
Block a user