diff options
author | Jean Boussier <[email protected]> | 2025-03-05 17:29:32 +0100 |
---|---|---|
committer | Jean Boussier <[email protected]> | 2025-03-05 18:57:21 +0100 |
commit | c224ca4feaff20cab03d76439bcbfb35d4e2f6b1 (patch) | |
tree | 8322334b65b84ff9d93764d45c1e00ffd414a1bf /string.c | |
parent | 53579e5718b82dd655cd7bb129c86b83ecdb625d (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.c | 4 |
1 files changed, 4 insertions, 0 deletions
@@ -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; } |