catch exceptions on workers and pass them to the scheduler (#93)

This commit is contained in:
Robert Nishihara
2016-06-11 15:44:56 -07:00
committed by Philipp Moritz
parent 61a0014c00
commit 41539141af
8 changed files with 38 additions and 15 deletions
+7 -3
View File
@@ -90,9 +90,13 @@ def main_loop(worker=global_worker):
def process_task(task): # wrapping these lines in a function should cause the local variables to go out of scope more quickly, which is useful for inspecting reference counts
func_name, args, return_objrefs = serialization.deserialize_task(worker.handle, task)
arguments = get_arguments_for_execution(worker.functions[func_name], args, worker) # get args from objstore
outputs = worker.functions[func_name].executor(arguments) # execute the function
store_outputs_in_objstore(return_objrefs, outputs, worker) # store output in local object store
ray.lib.notify_task_completed(worker.handle) # notify the scheduler that the task has completed
try:
outputs = worker.functions[func_name].executor(arguments) # execute the function
except Exception as e:
ray.lib.notify_task_completed(worker.handle, False, str(e)) # notify the scheduler that the task threw an exception
else:
store_outputs_in_objstore(return_objrefs, outputs, worker) # store output in local object store
ray.lib.notify_task_completed(worker.handle, True, "") # notify the scheduler that the task completed successfully
while True:
task = ray.lib.wait_for_next_task(worker.handle)
process_task(task)
+5 -3
View File
@@ -44,7 +44,7 @@ service Scheduler {
// Used by the worker to notify the scheduler about which objrefs a particular object contains
rpc AddContainedObjRefs(AddContainedObjRefsRequest) returns (AckReply);
// Used by the worker to report back and ask for more work
rpc WorkerReady(WorkerReadyRequest) returns (AckReply);
rpc NotifyTaskCompleted(NotifyTaskCompletedRequest) returns (AckReply);
// Get information about the scheduler state
rpc SchedulerInfo(SchedulerInfoRequest) returns (SchedulerInfoReply);
}
@@ -120,8 +120,10 @@ message DecrementRefCountRequest {
repeated uint64 objref = 1; // Object references whose reference count should be decremented. Duplicates will be decremented multiple times.
}
message WorkerReadyRequest {
uint64 workerid = 1; // ID of the worker which is ready
message NotifyTaskCompletedRequest {
uint64 workerid = 1; // ID of the worker which executed the task
bool task_succeeded = 2; // True if the task succeeded, false if it threw an exception
string error_message = 3; // The contents of the exception, if the task threw an exception
}
message ChangeCountRequest {
+6 -2
View File
@@ -662,10 +662,14 @@ PyObject* submit_task(PyObject* self, PyObject* args) {
PyObject* notify_task_completed(PyObject* self, PyObject* args) {
Worker* worker;
if (!PyArg_ParseTuple(args, "O&", &PyObjectToWorker, &worker)) {
PyObject* task_succeeded_obj;
const char* error_message_ptr;
if (!PyArg_ParseTuple(args, "O&Os", &PyObjectToWorker, &worker, &task_succeeded_obj, &error_message_ptr)) {
return NULL;
}
worker->notify_task_completed();
std::string error_message(error_message_ptr);
bool task_succeeded = PyObject_IsTrue(task_succeeded_obj);
worker->notify_task_completed(task_succeeded, error_message);
Py_RETURN_NONE;
}
+4 -1
View File
@@ -144,12 +144,15 @@ Status SchedulerService::ObjReady(ServerContext* context, const ObjReadyRequest*
return Status::OK;
}
Status SchedulerService::WorkerReady(ServerContext* context, const WorkerReadyRequest* request, AckReply* reply) {
Status SchedulerService::NotifyTaskCompleted(ServerContext* context, const NotifyTaskCompletedRequest* request, AckReply* reply) {
RAY_LOG(RAY_INFO, "worker " << request->workerid() << " reported back");
{
std::lock_guard<std::mutex> lock(avail_workers_lock_);
avail_workers_.push_back(request->workerid());
}
if (!request->task_succeeded()) {
RAY_LOG(RAY_FATAL, "The task on worker " << request->workerid() << " threw an exception with the following error message: " << request->error_message());
}
schedule();
return Status::OK;
}
+1 -1
View File
@@ -60,7 +60,7 @@ public:
Status RegisterWorker(ServerContext* context, const RegisterWorkerRequest* request, RegisterWorkerReply* reply) override;
Status RegisterFunction(ServerContext* context, const RegisterFunctionRequest* request, AckReply* reply) override;
Status ObjReady(ServerContext* context, const ObjReadyRequest* request, AckReply* reply) override;
Status WorkerReady(ServerContext* context, const WorkerReadyRequest* request, AckReply* reply) override;
Status NotifyTaskCompleted(ServerContext* context, const NotifyTaskCompletedRequest* request, AckReply* reply) override;
Status IncrementRefCount(ServerContext* context, const IncrementRefCountRequest* request, AckReply* reply) override;
Status DecrementRefCount(ServerContext* context, const DecrementRefCountRequest* request, AckReply* reply) override;
Status AddContainedObjRefs(ServerContext* context, const AddContainedObjRefsRequest* request, AckReply* reply) override;
+5 -3
View File
@@ -263,15 +263,17 @@ Task* Worker::receive_next_task() {
return task;
}
void Worker::notify_task_completed() {
void Worker::notify_task_completed(bool task_succeeded, std::string error_message) {
if (!connected_) {
RAY_LOG(RAY_FATAL, "Attempting to perform notify_task_completed, but connected_ = " << connected_ << ".");
}
ClientContext context;
WorkerReadyRequest request;
NotifyTaskCompletedRequest request;
request.set_workerid(workerid_);
request.set_task_succeeded(task_succeeded);
request.set_error_message(error_message);
AckReply reply;
scheduler_stub_->WorkerReady(&context, request, &reply);
scheduler_stub_->NotifyTaskCompleted(&context, request, &reply);
}
void Worker::disconnect() {
+4 -2
View File
@@ -71,8 +71,10 @@ class Worker {
void start_worker_service();
// wait for next task from the RPC system
Task* receive_next_task();
// tell the scheduler that we are done with the current task and request the next one
void notify_task_completed();
// tell the scheduler that we are done with the current task and request the
// next one, if task_succeeded is false, this tells the scheduler that the
// task threw an exception
void notify_task_completed(bool task_succeeded, std::string error_message);
// disconnect the worker
void disconnect();
// return connected_
+6
View File
@@ -78,3 +78,9 @@ try:
varargs_and_kwargs_exception_thrown = False
except:
varargs_and_kwargs_exception_thrown = True
# test throwing an exception
@ray.remote([], [])
def throw_exception_fct():
raise Exception("Test function intentionally failed.")