diff options
author | Peter Zhu <[email protected]> | 2024-05-01 10:01:02 -0400 |
---|---|---|
committer | Peter Zhu <[email protected]> | 2024-05-01 11:09:54 -0400 |
commit | 7ef8bb129ff16750429a7ede4397d0622954ca35 (patch) | |
tree | ca28b571c649a0750db0bab47b67464e19466cb7 | |
parent | e9e41ad6b0b94e69e375cb2cef84e7a241d7ef56 (diff) |
Fix memory leak in Ripper.sexp
rb_ast_dispose does not free the rb_ast_t causing it to be leaked. This
commit changes it to use rb_ast_free instead.
For example:
require "ripper"
10.times do
100_000.times do
Ripper.sexp("")
end
puts `ps -o rss= -p #{$$}`
end
Before:
27648
32512
37376
42240
47232
52224
57344
62208
67072
71936
After:
22784
22784
22784
22784
22912
22912
22912
22912
22912
22912
-rw-r--r-- | parse.y | 2 | ||||
-rw-r--r-- | test/ripper/test_ripper.rb | 8 |
2 files changed, 9 insertions, 1 deletions
@@ -16076,7 +16076,7 @@ rb_ruby_ripper_parse0(rb_parser_t *p) parser_prepare(p); p->ast = rb_ast_new(); ripper_yyparse((void*)p); - rb_ast_dispose(p->ast); + rb_ast_free(p->ast); p->ast = 0; p->eval_tree = 0; p->eval_tree_begin = 0; diff --git a/test/ripper/test_ripper.rb b/test/ripper/test_ripper.rb index 6061496d9c..f129a41be9 100644 --- a/test/ripper/test_ripper.rb +++ b/test/ripper/test_ripper.rb @@ -170,6 +170,14 @@ end end; end + def test_sexp_no_memory_leak + assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true) + 1_000_000.times do + Ripper.sexp("") + end + end; + end + class TestInput < self Input = Struct.new(:lines) do def gets |