Skip to content

Commit

Permalink
merge revision(s) 6c25291: [Backport #20145]
Browse files Browse the repository at this point in the history
	Memory leak when duplicating identhash

	[Bug #20145]

	Before this commit, both copy_compare_by_id and hash_copy will create a
	copy of the ST table, so the ST table created in copy_compare_by_id will
	be leaked.

	    h = { 1 => 2 }.compare_by_identity

	    10.times do
	      1_000_000.times do
	        h.select { false }
	      end

	      puts `ps -o rss= -p #{$$}`
	    end

	Before:

	    110736
	    204352
	    300272
	    395520
	    460704
	    476736
	    542000
	    604704
	    682624
	    770528

	After:

	    15504
	    16048
	    16144
	    16256
	    16320
	    16320
	    16752
	    16752
	    16752
	    16752
	---
	 hash.c                 | 10 +++++++++-
	 test/ruby/test_hash.rb | 10 ++++++++++
	 2 files changed, 19 insertions(+), 1 deletion(-)
  • Loading branch information
nurse committed Feb 1, 2024
1 parent f585171 commit aeffb5e
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 2 deletions.
10 changes: 9 additions & 1 deletion hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -1557,7 +1557,15 @@ hash_copy(VALUE ret, VALUE hash)
static VALUE
hash_dup_with_compare_by_id(VALUE hash)
{
return hash_copy(copy_compare_by_id(rb_hash_new(), hash), hash);
VALUE dup = hash_alloc_flags(rb_cHash, 0, Qnil, RHASH_ST_TABLE_P(hash));
if (RHASH_ST_TABLE_P(hash)) {
RHASH_SET_ST_FLAG(dup);
}
else {
RHASH_UNSET_ST_FLAG(dup);
}

return hash_copy(dup, hash);
}

static VALUE
Expand Down
10 changes: 10 additions & 0 deletions test/ruby/test_hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1458,6 +1458,16 @@ def test_compare_by_identity
assert_predicate(h.dup, :compare_by_identity?, bug8703)
end

def test_compare_by_identy_memory_leak
assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", "[Bug #20145]", rss: true)
begin;
h = { 1 => 2 }.compare_by_identity
1_000_000.times do
h.select { false }
end
end;
end

def test_same_key
bug9646 = '[ruby-dev:48047] [Bug #9646] Infinite loop at Hash#each'
h = @cls[a=[], 1]
Expand Down
2 changes: 1 addition & 1 deletion version.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 0
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
#define RUBY_PATCHLEVEL 4
#define RUBY_PATCHLEVEL 5

#include "ruby/version.h"
#include "ruby/internal/abi.h"
Expand Down

0 comments on commit aeffb5e

Please sign in to comment.