mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Added a TaskSignalledCallback to TaskQueue, which will be called instead of TaskFinishedCallback if the task exited abnormally. In Unix/TaskQueue.inc, check WIFSIGNALED if the task did not pass WIFEXITED, and call the TaskSignalledCallback if necessary. In Default/TaskQueue.inc, check for a return code of -2; if present, call the TaskSignalledCallback instead of the TaskFinishedCallback. Updated Compilation to pass a TaskSignalledCallback. Added diagnostics to indicate when a command signalled as well as when a command failed with either poor diagnostics or a non-1 exit code. (These match Clang’s diagnostics.) Added tests to ensure these diagnostics are emitted when the frontend crashes or fails an assertion (if assertions are available). This fixes <rdar://problem/16012199>. Swift SVN r13654
91 lines
2.9 KiB
C++
91 lines
2.9 KiB
C++
//===--- TaskQueue.cpp - Task Execution Work Queue ------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// \brief This file includes the appropriate platform-specific TaskQueue
|
|
/// implementation (or the default serial fallback if one is not available),
|
|
/// as well as any platform-agnostic TaskQueue functionality.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/Basic/TaskQueue.h"
|
|
|
|
using namespace swift;
|
|
using namespace swift::sys;
|
|
|
|
// Include the correct TaskQueue implementation.
|
|
#if LLVM_ON_UNIX
|
|
#include "Unix/TaskQueue.inc"
|
|
#else
|
|
#include "Default/TaskQueue.inc"
|
|
#endif
|
|
|
|
TaskQueue::TaskQueue(unsigned NumberOfParallelTasks)
|
|
: NumberOfParallelTasks(NumberOfParallelTasks) {}
|
|
|
|
TaskQueue::~TaskQueue() = default;
|
|
|
|
// DummyTaskQueue implementation
|
|
|
|
DummyTaskQueue::DummyTaskQueue(unsigned NumberOfParallelTasks)
|
|
: TaskQueue(NumberOfParallelTasks) {}
|
|
|
|
DummyTaskQueue::~DummyTaskQueue() = default;
|
|
|
|
void DummyTaskQueue::addTask(const char *ExecPath, ArrayRef<const char *> Args,
|
|
ArrayRef<const char *> Env, void *Context) {
|
|
QueuedTasks.emplace(
|
|
std::unique_ptr<DummyTask>(new DummyTask(ExecPath, Args, Env, Context)));
|
|
}
|
|
|
|
bool DummyTaskQueue::execute(TaskQueue::TaskBeganCallback Began,
|
|
TaskQueue::TaskFinishedCallback Finished,
|
|
TaskQueue::TaskSignalledCallback Signalled) {
|
|
typedef std::pair<pid_t, std::unique_ptr<DummyTask>> PidTaskPair;
|
|
std::queue<PidTaskPair> ExecutingTasks;
|
|
|
|
bool SubtaskFailed = false;
|
|
|
|
pid_t Pid = 0;
|
|
|
|
unsigned MaxNumberOfParallelTasks = getNumberOfParallelTasks();
|
|
|
|
while ((!QueuedTasks.empty() && !SubtaskFailed) ||
|
|
!ExecutingTasks.empty()) {
|
|
// Enqueue additional tasks if we have additional tasks, we aren't already
|
|
// at the parallel limit, and no earlier subtasks have failed.
|
|
while (!SubtaskFailed && !QueuedTasks.empty() &&
|
|
ExecutingTasks.size() < MaxNumberOfParallelTasks) {
|
|
std::unique_ptr<DummyTask> T(QueuedTasks.front().release());
|
|
QueuedTasks.pop();
|
|
|
|
if (Began)
|
|
Began(++Pid, T->Context);
|
|
|
|
ExecutingTasks.push(PidTaskPair(Pid, std::move(T)));
|
|
}
|
|
|
|
// Finish the first scheduled task.
|
|
PidTaskPair P = std::move(ExecutingTasks.front());
|
|
ExecutingTasks.pop();
|
|
|
|
if (Finished) {
|
|
std::string Output = "Output placeholder\n";
|
|
if (Finished(P.first, 0, Output, P.second->Context) ==
|
|
TaskFinishedResponse::StopExecution)
|
|
SubtaskFailed = true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|