Skip to content

Use a T_DATA for cross_ractor_require #13531

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

jhawthorn
Copy link
Member

Fixes Bug #21090

The struct was previously allocated on the stack, which could be freed if the Thread is terminated. Moving this to a T_DATA on the heap should mean this is no longer an issue.

1000.times { Ractor.new { th = Thread.new { require "rbconfig" }; Thread.pass }.take }

Previously this would segfault, due to accessing the Thread's memory after it was terminated (when the Ractor exits). Now it prints 1000 times:

#<Thread:0x000077b21ddaa5e0 run> terminated with exception (report_on_exception is true):
The port was already closed (Ractor::ClosedError)

The error comes from trying to send the result of the require back through the port. Maybe we could have a better error message, but that seems pretty reasonable to me given how much of an edge case this is.

cc @ko1 @luke-gru

jhawthorn and others added 2 commits June 5, 2025 13:56
Previously rb_ractor_interrupt_exec would use an intermediate function
to create a new thread with the actual target function, replacing the
data being passed in with a piece of malloc memory holding the "next"
function and the original data.

Because of this, passing rb_interrupt_exec_flag_value_data to
rb_ractor_interrupt_exec didn't have the intended effect of allowing
data to be passed in and marked.

This commit adds a rb_interrupt_exec_flag_new_thread flag, which
both simplifies the implementation and allows the original data to be
marked.
[Bug #21090]

The struct was previously allocated on the stack, which could be freed
if the Thread is terminated. Moving this to a T_DATA on the heap should
mean this is no longer an issue.

1000.times { Ractor.new { th = Thread.new { require "rbconfig" }; Thread.pass }.take }

Co-authored-by: Luke Gruber <luke.gruber@shopify.com>
@ko1 ko1 self-requested a review June 6, 2025 04:38
@ko1
Copy link
Contributor

ko1 commented Jun 6, 2025

it should be problem with ractor local gc.

  • pass simple malloc'ed memory
  • make the object shareable

hmm, other ideas?

Comment on lines +2240 to +2249
static void
cross_ractor_require_mark(void *ptr)
{
struct cross_ractor_require *crr = (struct cross_ractor_require *)ptr;
rb_gc_mark(crr->port);
rb_gc_mark(crr->result);
rb_gc_mark(crr->exception);
rb_gc_mark(crr->feature);
rb_gc_mark(crr->module);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants