Skip to content

Add missing lock in rb_gc_impl_define_finalizer #13151

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

Merged
merged 1 commit into from
Apr 22, 2025

Conversation

byroot
Copy link
Member

@byroot byroot commented Apr 22, 2025

objspace->finalizer_table must be synchronized,
otherwise concurrent insertion from multiple ractors will cause a crash.

Repro:

ractors = 5.times.map do |i|
  Ractor.new do
    100_000.times.map do
      o = Object.new
      ObjectSpace.define_finalizer(o, ->(id) {})
      o
    end
  end
end

ractors.each(&:take)

FYI: @tenderlove @jhawthorn @etiennebarrie

`objspace->finalizer_table` must be synchronized,
otherwise concurrent insertion from multiple ractors
will cause a crash.

Repro:

```ruby
ractors = 5.times.map do |i|
  Ractor.new do
    100_000.times.map do
      o = Object.new
      ObjectSpace.define_finalizer(o, ->(id) {})
      o
    end
  end
end

ractors.each(&:take)
```
@byroot byroot enabled auto-merge (rebase) April 22, 2025 17:49
Copy link

launchable-app bot commented Apr 22, 2025

All Tests passed!

✖️no tests failed ✔️61959 tests passed(2 flakes)

@@ -2834,6 +2834,8 @@ rb_gc_impl_define_finalizer(void *objspace_ptr, VALUE obj, VALUE block)

RBASIC(obj)->flags |= FL_FINALIZE;

int lev = rb_gc_vm_lock();

Copy link
Contributor

Choose a reason for hiding this comment

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

I can't add a line comment since you didn't modify that block, but do you have to unlock at 2849 before the early return?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch 6d0dd7d

@@ -973,6 +973,8 @@ rb_gc_impl_define_finalizer(void *objspace_ptr, VALUE obj, VALUE block)

RBASIC(obj)->flags |= FL_FINALIZE;

int lev = rb_gc_vm_lock();
Copy link
Contributor

Choose a reason for hiding this comment

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

(as above with early return)

@byroot byroot merged commit 7c30bd5 into ruby:master Apr 22, 2025
86 checks passed
@byroot byroot deleted the define-finalizer-lock branch April 23, 2025 05:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants