mirror of
https://github.com/ruby/ruby.git
synced 2026-10-28 16:36:20 +08:00
Ractor: do not leak generic_fields_lock when the insert raises
Adding a generic-fields entry takes the VM-wide generic_fields_lock and then calls st_insert, which mallocs when the table grows. With this Ractor's GC disabled the allocation cannot fall back to a collection, so it can raise NoMemoryError -- and the raise skipped both gf_unlock() and the matching rb_gc_local_enable(). A leaked generic_fields_lock hangs every later access to generic fields, including the marking of any Ractor's local GC, so an otherwise recoverable NoMemoryError turned into a deadlock. Unwind through a tag instead. While here, drop three things that no longer match the code: a basket payload comment describing a generic-ivar map field that was removed, the unused st_table placeholder left in ractor_basket_new, and two comments in variable.c still describing the per-Ractor generic-fields tables that the single global table replaced. This commit also carries the mechanical translation of the Japanese comments in these two files, which was in progress in the same working tree. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
4a13043ae6
commit
9d3b43fda9
2 files changed
+16
-10
Notes:
git
2026-08-07 07:28:55 +00:00
No files matched your search
+9
-1
@@ -25,6 +25,7 @@
|
||||
#include "internal/compilers.h"
|
||||
#include "internal/error.h"
|
||||
#include "internal/eval.h"
|
||||
#include "eval_intern.h"
|
||||
#include "internal/hash.h"
|
||||
#include "internal/object.h"
|
||||
#include "internal/gc.h"
|
||||
@@ -1456,10 +1457,17 @@ rb_obj_set_fields(VALUE obj, VALUE fields_obj, ID field_name, VALUE original_fie
|
||||
* can still raise NoMemoryError, and leaking gf_lock hangs every later
|
||||
* generic-fields access: unwind through a tag. */
|
||||
bool gc_disabled = RTEST(rb_gc_local_disable_no_rest());
|
||||
rb_execution_context_t *insert_ec = GET_EC();
|
||||
enum ruby_tag_type state;
|
||||
gf_lock();
|
||||
st_insert(generic_fields_tbl_, (st_data_t)obj, (st_data_t)fields_obj);
|
||||
EC_PUSH_TAG(insert_ec);
|
||||
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
|
||||
st_insert(generic_fields_tbl_, (st_data_t)obj, (st_data_t)fields_obj);
|
||||
}
|
||||
EC_POP_TAG();
|
||||
gf_unlock();
|
||||
if (!gc_disabled) rb_gc_local_enable();
|
||||
if (state != TAG_NONE) EC_JUMP_TAG(insert_ec, state);
|
||||
RB_OBJ_WRITTEN(obj, original_fields_obj, fields_obj);
|
||||
|
||||
rb_execution_context_t *ec = GET_EC();
|
||||
|
||||
Reference in new issue
Block a user