Skip to content

Commit

Permalink
Safely handle attempts to borrow from closed Ractors
Browse files Browse the repository at this point in the history
  • Loading branch information
rm155 committed Apr 12, 2024
1 parent 635732e commit d6a9f46
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 5 deletions.
31 changes: 27 additions & 4 deletions gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -3764,7 +3764,7 @@ mark_received_received_obj_tbl(rb_objspace_t *objspace)
}

static void
removed_received_obj_list(rb_objspace_t *objspace, uintptr_t borrowing_id)
remove_received_obj_list(rb_objspace_t *objspace, uintptr_t borrowing_id)
{
rb_native_mutex_lock(&objspace->received_obj_tbl_lock);
st_data_t data;
Expand Down Expand Up @@ -3899,7 +3899,9 @@ borrowing_exit(VALUE args)

if (!!finished_target) {
rb_borrowing_sync_lock(finished_target);
removed_received_obj_list(finished_target->local_objspace, finished_borrowing_id);
if (LIKELY(!finished_target->borrowing_sync.borrowing_closed)) {
remove_received_obj_list(finished_target->local_objspace, finished_borrowing_id);
}
rb_borrowing_sync_unlock(finished_target);
borrowing_count_decrement(finished_target);
#if VM_CHECK_MODE > 0
Expand Down Expand Up @@ -3927,7 +3929,7 @@ run_redirected_func(VALUE args)
}

VALUE
rb_run_with_redirected_allocation(rb_ractor_t *target_ractor, VALUE (*func)(VALUE), VALUE func_args)
rb_attempt_run_with_redirected_allocation(rb_ractor_t *target_ractor, VALUE (*func)(VALUE), VALUE func_args, bool *borrowing_success)
{
struct borrowing_data_args borrowing_data = {
.borrower = GET_RACTOR(),
Expand All @@ -3939,7 +3941,28 @@ rb_run_with_redirected_allocation(rb_ractor_t *target_ractor, VALUE (*func)(VALU
};
VALUE bd_args = (VALUE)&borrowing_data;
borrowing_enter(bd_args);
return rb_ensure(run_redirected_func, bd_args, borrowing_exit, bd_args);
if (UNLIKELY(target_ractor && target_ractor->borrowing_sync.borrowing_closed)) {
if (borrowing_success) *borrowing_success = false;
borrowing_exit(bd_args);
return Qfalse;
}
else {
if (borrowing_success) *borrowing_success = true;
return rb_ensure(run_redirected_func, bd_args, borrowing_exit, bd_args);
}
}

VALUE
rb_run_with_redirected_allocation(rb_ractor_t *target_ractor, VALUE (*func)(VALUE), VALUE func_args)
{
bool success;
VALUE ret = rb_attempt_run_with_redirected_allocation(target_ractor, func, func_args, &success);
if (LIKELY(success)) {
return ret;
}
else {
rb_bug("Failed to borrow from Ractor #%d", target_ractor->pub.id);
}
}

bool
Expand Down
3 changes: 2 additions & 1 deletion ractor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1103,7 +1103,7 @@ ractor_send(rb_execution_context_t *ec, rb_ractor_t *r, VALUE obj, VALUE move)
.success = false,
};

VALUE ret = rb_run_with_redirected_allocation(r, ractor_send_given_redirected_allocation, (VALUE)&args);
VALUE ret = rb_attempt_run_with_redirected_allocation(r, ractor_send_given_redirected_allocation, (VALUE)&args, NULL);
if (!args.success) {
rb_raise(rb_eRactorClosedError, "The incoming-port is already closed");
}
Expand Down Expand Up @@ -2374,6 +2374,7 @@ rb_ractor_teardown(rb_execution_context_t *ec)
rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
rb_borrowing_sync_lock(cr);
rb_ractor_wait_for_no_borrowers(cr);
cr->borrowing_sync.borrowing_closed = true;
ractor_close_incoming(ec, cr);
ractor_close_outgoing(ec, cr);
rb_borrowing_sync_unlock(cr);
Expand Down
1 change: 1 addition & 0 deletions ractor_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ struct rb_ractor_struct {
rb_atomic_t borrower_count;
rb_nativethread_cond_t no_borrowers;

bool borrowing_closed;
bool borrowing_allowed;
rb_nativethread_cond_t borrowing_allowed_cond;
rb_nativethread_lock_t borrowing_allowed_lock;
Expand Down
1 change: 1 addition & 0 deletions vm_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -1818,6 +1818,7 @@ VALUE rb_binding_alloc(VALUE klass);
VALUE rb_proc_alloc(VALUE klass);
VALUE rb_proc_dup(VALUE self);

VALUE rb_attempt_run_with_redirected_allocation(rb_ractor_t *target_ractor, VALUE (*func)(VALUE), VALUE func_args, bool *borrowing_success);
VALUE rb_run_with_redirected_allocation(rb_ractor_t *target_ractor, VALUE (*func)(VALUE), VALUE args);
bool rb_redirecting_allocation(void);
rb_ractor_t *rb_current_allocating_ractor(void);
Expand Down

0 comments on commit d6a9f46

Please sign in to comment.