summaryrefslogtreecommitdiff
path: root/variable.c
diff options
context:
space:
mode:
authorJohn Hawthorn <[email protected]>2024-11-19 21:05:39 -0800
committerJohn Hawthorn <[email protected]>2024-11-23 01:16:48 -0800
commit34e36a72a7a01e720140fc48a31f3444b3b62c53 (patch)
treebc3ffe37ffb005cfe01409bef5c241e3b32624f9 /variable.c
parenta8ebc596d6c4df190df269668dc0168e96fff0fb (diff)
Ensure global variable traces are freed at exit
ASAN_OPTIONS="detect_leaks=1" RUBY_FREE_AT_EXIT=1 ./miniruby -e 'trace_var(:$x){}'
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/12146
Diffstat (limited to 'variable.c')
-rw-r--r--variable.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/variable.c b/variable.c
index e4a24f44a0..bc255b6b5f 100644
--- a/variable.c
+++ b/variable.c
@@ -453,15 +453,27 @@ struct rb_global_entry {
bool ractor_local;
};
+static void
+free_global_variable(struct rb_global_variable *var)
+{
+ RUBY_ASSERT(var->counter == 0);
+
+ struct trace_var *trace = var->trace;
+ while (trace) {
+ struct trace_var *next = trace->next;
+ xfree(trace);
+ trace = next;
+ }
+ xfree(var);
+}
+
static enum rb_id_table_iterator_result
free_global_entry_i(VALUE val, void *arg)
{
struct rb_global_entry *entry = (struct rb_global_entry *)val;
- if (entry->var->counter == 1) {
- ruby_xfree(entry->var);
- }
- else {
- entry->var->counter--;
+ entry->var->counter--;
+ if (entry->var->counter == 0) {
+ free_global_variable(entry->var);
}
ruby_xfree(entry);
return ID_TABLE_DELETE;
@@ -1007,13 +1019,7 @@ rb_alias_variable(ID name1, ID name2)
}
var->counter--;
if (var->counter == 0) {
- struct trace_var *trace = var->trace;
- while (trace) {
- struct trace_var *next = trace->next;
- xfree(trace);
- trace = next;
- }
- xfree(var);
+ free_global_variable(var);
}
}
else {