зеркало из https://github.com/github/ruby.git
Fix leak of AST when Ripper#compile_error jumps
For example, the following script leaks: class MyRipper < Ripper def initialize(src, &blk) super(src) @blk = blk end def compile_error(msg) = @blk.call(msg) end def call_parse = MyRipper.new("/") { |msg| return msg }.parse 10.times do 100_000.times do call_parse end puts `ps -o rss= -p #{$$}` end Before: 93952 169040 244224 318784 394432 468224 544048 618560 693776 768384 After: 19776 19776 20352 20880 20912 21408 21328 21152 21472 20944
This commit is contained in:
Родитель
70b4f45d9f
Коммит
6358397490
4
parse.y
4
parse.y
|
@ -15608,6 +15608,10 @@ rb_ruby_parser_free(void *ptr)
|
|||
struct parser_params *p = (struct parser_params*)ptr;
|
||||
struct local_vars *local, *prev;
|
||||
|
||||
if (p->ast) {
|
||||
rb_ast_free(p->ast);
|
||||
}
|
||||
|
||||
#ifndef RIPPER
|
||||
if (p->tokens) {
|
||||
rb_parser_ary_free(p, p->tokens);
|
||||
|
|
|
@ -1743,4 +1743,26 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
|
|||
parse('case 0; in {a:}; end', :on_hshptn) {thru_hshptn = true}
|
||||
assert_equal true, thru_hshptn
|
||||
end
|
||||
|
||||
def test_return_out_of_compile_error_no_memory_leak
|
||||
assert_no_memory_leak(%w(-rripper), "#{<<~'begin;'}", "#{<<~'end;'}", rss: true)
|
||||
class MyRipper < Ripper
|
||||
def initialize(src, &blk)
|
||||
super(src)
|
||||
@blk = blk
|
||||
end
|
||||
|
||||
def compile_error(msg) = @blk.call(msg)
|
||||
end
|
||||
|
||||
def call_parse = MyRipper.new("/") { |msg| return msg }.parse
|
||||
|
||||
# Check that call_parse does return a syntax error
|
||||
raise "call_parse should return a syntax error" unless call_parse
|
||||
begin;
|
||||
100_000.times do
|
||||
call_parse
|
||||
end
|
||||
end;
|
||||
end
|
||||
end if ripper_test
|
||||
|
|
Загрузка…
Ссылка в новой задаче