summaryrefslogtreecommitdiff
path: root/string.c
diff options
context:
space:
mode:
authorJean Boussier <[email protected]>2025-03-05 17:29:32 +0100
committerJean Boussier <[email protected]>2025-03-05 18:57:21 +0100
commitc224ca4feaff20cab03d76439bcbfb35d4e2f6b1 (patch)
tree8322334b65b84ff9d93764d45c1e00ffd414a1bf /string.c
parent53579e5718b82dd655cd7bb129c86b83ecdb625d (diff)
Fix a race condition with interned strings sweeping.
[Bug #21172] This fixes a rare CI failure. The timeline of the race condition is: - A `"foo" oid=1` string is interned. - `"foo" oid=1` is no longer referenced and will be swept in the future. - Another `"foo" oid=2` string is interned. - `register_fstring` finds `"foo" oid=1`, but since it is about to be swept, removes it from `fstring_table` and insert `"foo" oid=2` instead. - `"foo" oid=1` is swept, since it has the `RSTRING_FSTR` flag, a `st_delete` is issued in `fstring_table` which removes `"foo" oid=2`. I don't know how to reproduce this bug consistently in a single test case.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/12857
Diffstat (limited to 'string.c')
-rw-r--r--string.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/string.c b/string.c
index c1b43f800b..611883dd40 100644
--- a/string.c
+++ b/string.c
@@ -433,6 +433,10 @@ fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t data, int exist
if (rb_objspace_garbage_object_p(str)) {
arg->fstr = Qundef;
+ // When RSTRING_FSTR strings are swept, they call `st_delete`.
+ // To avoid a race condition if an equivalent string was inserted
+ // we must remove the flag immediately.
+ FL_UNSET_RAW(str, RSTRING_FSTR);
return ST_DELETE;
}