ruby_memcheck 1.3.2 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43086325741d10b10981f494f7351aa5877d413d5f14f808ed9e3b574e0392a5
4
- data.tar.gz: c2894cc1143bc4383b7503ac4b4a2862250560a97b36c2e9f7c3ef38554e56e4
3
+ metadata.gz: 597a64c7109c460a09cfaa57715d6f26a50104e8137c5184d9bf5f658954d07f
4
+ data.tar.gz: e9524cbead271b0a5eb8abf85213c59d97d6629d1b6e2e2e3c03d0e94beb7970
5
5
  SHA512:
6
- metadata.gz: 82769e6405cd5f79a5b2d04611c4d37bcac5f76b665541b1448c7d78eb86f890f96291703786aaf47a6026b70ce577e64142913642fd320f631701311b852c61
7
- data.tar.gz: 64470c0bc4683e23e4609372a765f95ad12feb65801924b88aa5f638d1924bc56567c16d81eb541416324186d8866a40b4bd32645e7d3591c2e3a3fbb617bc92
6
+ metadata.gz: 2b38c33923e1370245b6184b5b4f16b993819bf02dc3fc76a4fc152c2ae10f50d4597b507983b5fafbbcc09933fd63e06c2c057f55f30c613ece717c68e74e45
7
+ data.tar.gz: 30a0d75f4268ee39cc34cf865bfb7a0414f4bb89ce10995fd8e55517cc8090761c4d21356e908b2d93adf97a5e8200019e577cb4ba61d2361e7caca5097b6049
@@ -0,0 +1,23 @@
1
+ # .github/workflows/cla.yml
2
+ name: Contributor License Agreement (CLA)
3
+
4
+ on:
5
+ pull_request_target:
6
+ types: [opened, synchronize]
7
+ issue_comment:
8
+ types: [created]
9
+
10
+ jobs:
11
+ cla:
12
+ runs-on: ubuntu-latest
13
+ if: |
14
+ (github.event.issue.pull_request
15
+ && !github.event.issue.pull_request.merged_at
16
+ && contains(github.event.comment.body, 'signed')
17
+ )
18
+ || (github.event.pull_request && !github.event.pull_request.merged)
19
+ steps:
20
+ - uses: Shopify/shopify-cla-action@v1
21
+ with:
22
+ github-token: ${{ secrets.GITHUB_TOKEN }}
23
+ cla-token: ${{ secrets.CLA_TOKEN }}
@@ -7,7 +7,6 @@ jobs:
7
7
  fail-fast: false
8
8
  matrix:
9
9
  entry:
10
- - { ruby: '2.7', allowed-failure: false }
11
10
  - { ruby: '3.0', allowed-failure: false }
12
11
  - { ruby: '3.1', allowed-failure: false }
13
12
  - { ruby: '3.2', allowed-failure: false }
@@ -24,9 +23,9 @@ jobs:
24
23
  - run: sudo apt-get install -y libc6-dbg
25
24
  - name: Install Valgrind from source
26
25
  run: |
27
- wget https://sourceware.org/pub/valgrind/valgrind-3.20.0.tar.bz2
28
- tar xvf valgrind-3.20.0.tar.bz2
29
- cd valgrind-3.20.0
26
+ wget https://sourceware.org/pub/valgrind/valgrind-3.21.0.tar.bz2
27
+ tar xvf valgrind-3.21.0.tar.bz2
28
+ cd valgrind-3.21.0
30
29
  ./configure
31
30
  make
32
31
  sudo make install
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2021 Peter Zhu
3
+ Copyright 2021-present, Shopify Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -61,9 +61,9 @@ gem install ruby_memcheck
61
61
  > You can install Valgrind from source using the following commands:
62
62
  > ```
63
63
  > sudo apt-get install -y libc6-dbg
64
- > wget https://sourceware.org/pub/valgrind/valgrind-3.20.0.tar.bz2
65
- > tar xvf valgrind-3.20.0.tar.bz2
66
- > cd valgrind-3.20.0
64
+ > wget https://sourceware.org/pub/valgrind/valgrind-3.21.0.tar.bz2
65
+ > tar xvf valgrind-3.21.0.tar.bz2
66
+ > cd valgrind-3.21.0
67
67
  > ./configure
68
68
  > make
69
69
  > sudo make install
@@ -84,12 +84,6 @@ The easiest way to use this gem is to use it on your test suite (minitest or RSp
84
84
  require "ruby_memcheck/rspec/rake_task"
85
85
  ```
86
86
 
87
- 1. Configure the gem by calling `RubyMemcheck.config`. You must pass it your binary name. This is the same value you passed into `create_makefile` in your `extconf.rb` file. Make sure this value is correct or it will filter out almost everything as a false-positive!
88
-
89
- ```ruby
90
- RubyMemcheck.config(binary_name: "your_binary_name")
91
- ```
92
-
93
87
  1. Setup the test task for your test framework.
94
88
  - **minitest**
95
89
 
@@ -145,18 +139,17 @@ The easiest way to use this gem is to use it on your test suite (minitest or RSp
145
139
 
146
140
  ## Configuration
147
141
 
148
- When you run `RubyMemcheck.config`, you are creating a default `RubyMemcheck::Configuration`. By default, the Rake tasks for minitest and RSpec will use this configuration. You can also manually pass in a `Configuration` object as the first argument to the constructor of `RubyMemcheck::TestTask` or `RubyMemcheck::RSpec::RakeTask` to use a different `Configuration` object rather than the default one.
142
+ If you want to override any of the default configurations you can call `RubyMemcheck.config` after `require "ruby_memcheck"`. This will create a default `RubyMemcheck::Configuration`. By default, the Rake tasks for minitest and RSpec will use this configuration. You can also manually pass in a `Configuration` object as the first argument to the constructor of `RubyMemcheck::TestTask` or `RubyMemcheck::RSpec::RakeTask` to use a different `Configuration` object rather than the default one.
149
143
 
150
144
  `RubyMemcheck::Configuration` accepts a variety of keyword arguments. Here are all the arguments:
151
145
 
152
- - `binary_name`: Required. The binary name of your native extension gem. This is the same value you passed into `create_makefile` in your `extconf.rb` file.
153
146
  - `ruby`: Optional. The command to run to invoke Ruby. Defaults to the Ruby that is currently being used.
154
147
  - `valgrind`: Optional. The command to run to invoke Valgrind. Defaults to the string `"valgrind"`.
155
148
  - `valgrind_options`: Optional. Array of options to pass into Valgrind. This is only present as an escape hatch, so avoid using it. This may be deprecated or removed in future versions.
156
149
  - `valgrind_suppressions_dir`: Optional. The string path of the directory that stores suppression files for Valgrind. See the [`Suppression files`](#suppression-files) section for more details. Defaults to `suppressions`.
157
150
  - `valgrind_generate_suppressions`: Optional. Whether suppressions should also be outputted along with the errors. the [`Suppression files`](#suppression-files) section for more details. Defaults to `false`.
158
151
  - `skipped_ruby_functions`: Optional. Ruby functions that are ignored because they are considered a call back into Ruby. This is only present as an escape hatch, so avoid using it. If you find another Ruby function that is a false positive because it calls back into Ruby, please send a patch into this repo. Otherwise, use a Valgrind suppression file.
159
- - `valgrind_xml_dir`: Optional. The directory to store temporary XML files for Valgrind. It defaults to a temporary directory. This is present for development debugging, so you shouldn't have to use it.
152
+ - `temp_dir`: Optional. The directory to store temporary files. It defaults to a temporary directory. This is present for development debugging, so you shouldn't have to use it.
160
153
  - `output_io`: Optional. The `IO` object to output Valgrind errors to. Defaults to standard error.
161
154
  - `filter_all_errors`: Optional. Whether to filter all kinds of Valgrind errors (not just memory leaks). This feature should only be used if you're encountering a large number of illegal memory accesses coming from Ruby. If you need to use this feature, you may have found a bug inside of Ruby. Consider reporting it to the [Ruby bug tracker](https://bugs.ruby-lang.org/projects/ruby-master/issues/new). Defaults to `false`.
162
155
 
data/Rakefile CHANGED
@@ -11,9 +11,16 @@ Rake::TestTask.new(test: "test:compile") do |t|
11
11
  end
12
12
 
13
13
  namespace :test do
14
- Rake::ExtensionTask.new("ruby_memcheck_c_test") do |ext|
14
+ Rake::ExtensionTask.new("ruby_memcheck_c_test_one") do |ext|
15
15
  ext.ext_dir = "test/ruby_memcheck/ext"
16
16
  ext.lib_dir = "test/ruby_memcheck/ext"
17
+ ext.config_script = "extconf_one.rb"
18
+ end
19
+
20
+ Rake::ExtensionTask.new("ruby_memcheck_c_test_two") do |ext|
21
+ ext.ext_dir = "test/ruby_memcheck/ext"
22
+ ext.lib_dir = "test/ruby_memcheck/ext"
23
+ ext.config_script = "extconf_two.rb"
17
24
  end
18
25
  end
19
26
 
@@ -31,14 +31,14 @@ module RubyMemcheck
31
31
  /\Arb_yield/,
32
32
  ].freeze
33
33
 
34
- attr_reader :binary_name
35
34
  attr_reader :ruby
36
35
  attr_reader :valgrind
37
36
  attr_reader :valgrind_options
38
37
  attr_reader :valgrind_suppression_files
39
38
  attr_reader :valgrind_generate_suppressions
40
39
  attr_reader :skipped_ruby_functions
41
- attr_reader :valgrind_xml_dir
40
+ attr_reader :temp_dir
41
+ attr_reader :loaded_features_file
42
42
  attr_reader :output_io
43
43
  attr_reader :filter_all_errors
44
44
 
@@ -46,18 +46,19 @@ module RubyMemcheck
46
46
  alias_method :filter_all_errors?, :filter_all_errors
47
47
 
48
48
  def initialize(
49
- binary_name:,
49
+ binary_name: nil,
50
50
  ruby: FileUtils::RUBY,
51
51
  valgrind: DEFAULT_VALGRIND,
52
52
  valgrind_options: DEFAULT_VALGRIND_OPTIONS,
53
53
  valgrind_suppressions_dir: DEFAULT_VALGRIND_SUPPRESSIONS_DIR,
54
54
  valgrind_generate_suppressions: false,
55
55
  skipped_ruby_functions: DEFAULT_SKIPPED_RUBY_FUNCTIONS,
56
- valgrind_xml_dir: Dir.mktmpdir,
56
+ temp_dir: Dir.mktmpdir,
57
57
  output_io: $stderr,
58
58
  filter_all_errors: false
59
59
  )
60
- @binary_name = binary_name
60
+ warn("ruby_memcheck: binary_name is no longer required for configuration") if binary_name
61
+
61
62
  @ruby = ruby
62
63
  @valgrind = valgrind
63
64
  @valgrind_options = valgrind_options
@@ -69,18 +70,18 @@ module RubyMemcheck
69
70
  @output_io = output_io
70
71
  @filter_all_errors = filter_all_errors
71
72
 
72
- if valgrind_xml_dir
73
- valgrind_xml_dir = File.expand_path(valgrind_xml_dir)
74
- FileUtils.mkdir_p(valgrind_xml_dir)
75
- @valgrind_xml_dir = valgrind_xml_dir
76
- @valgrind_options += [
77
- "--xml=yes",
78
- # %p will be replaced with the PID
79
- # This prevents forking and shelling out from generating a corrupted XML
80
- # See --log-file from https://valgrind.org/docs/manual/manual-core.html
81
- "--xml-file=#{File.join(valgrind_xml_dir, "%p.out")}",
82
- ]
83
- end
73
+ temp_dir = File.expand_path(temp_dir)
74
+ FileUtils.mkdir_p(temp_dir)
75
+ @temp_dir = temp_dir
76
+ @valgrind_options += [
77
+ "--xml=yes",
78
+ # %p will be replaced with the PID
79
+ # This prevents forking and shelling out from generating a corrupted XML
80
+ # See --log-file from https://valgrind.org/docs/manual/manual-core.html
81
+ "--xml-file=#{File.join(temp_dir, "%p.xml")}",
82
+ ]
83
+
84
+ @loaded_features_file = Tempfile.create("", @temp_dir)
84
85
  end
85
86
 
86
87
  def command(*args)
@@ -97,6 +98,7 @@ module RubyMemcheck
97
98
  valgrind_suppression_files.map { |f| "--suppressions=#{f}" },
98
99
  valgrind_generate_suppressions ? "--gen-suppressions=all" : "",
99
100
  ruby,
101
+ "-r" + File.expand_path(File.join(__dir__, "test_helper.rb")),
100
102
  args,
101
103
  ].flatten.join(" ")
102
104
  end
@@ -112,14 +114,7 @@ module RubyMemcheck
112
114
  versions << RUBY_ENGINE
113
115
 
114
116
  versions.map do |version|
115
- old_format_files = Dir[File.join(dir, "#{binary_name}_#{version}.supp")]
116
-
117
- unless old_format_files.empty?
118
- warn("ruby_memcheck: please migrate your suppression filenames from " \
119
- "`gem_name_ruby-3.1.0.supp` to `ruby-3.1.0.supp` (drop the gem name from the filename)")
120
- end
121
-
122
- old_format_files + Dir[File.join(dir, "#{version}.supp")]
117
+ Dir[File.join(dir, "#{version}.supp")]
123
118
  end.flatten
124
119
  end
125
120
  end
@@ -2,10 +2,12 @@
2
2
 
3
3
  module RubyMemcheck
4
4
  class Frame
5
- attr_reader :configuration, :fn, :obj, :file, :line
5
+ attr_reader :configuration, :loaded_binaries, :fn, :obj, :file, :line
6
6
 
7
- def initialize(configuration, frame_xml)
7
+ def initialize(configuration, loaded_binaries, frame_xml)
8
8
  @configuration = configuration
9
+ @loaded_binaries = loaded_binaries
10
+
9
11
  @fn = frame_xml.at_xpath("fn")&.content
10
12
  @obj = frame_xml.at_xpath("obj")&.content
11
13
  # file and line may not be available
@@ -24,8 +26,14 @@ module RubyMemcheck
24
26
  def in_binary?
25
27
  return false unless obj
26
28
 
27
- binary_name_without_ext = File.join(File.dirname(obj), File.basename(obj, ".*"))
28
- binary_name_without_ext.end_with?(File.join("", configuration.binary_name))
29
+ loaded_binaries.include?(obj)
30
+ end
31
+
32
+ def binary_init_func?
33
+ return false unless in_binary?
34
+
35
+ binary_name = File.basename(obj, ".*")
36
+ fn == "Init_#{binary_name}"
29
37
  end
30
38
 
31
39
  def to_s
@@ -5,9 +5,8 @@ require "rspec/core/rake_task"
5
5
  module RubyMemcheck
6
6
  module RSpec
7
7
  class RakeTask < ::RSpec::Core::RakeTask
8
- include TestTaskReporter
9
-
10
8
  attr_reader :configuration
9
+ attr_reader :reporter
11
10
 
12
11
  def initialize(*args)
13
12
  @configuration =
@@ -23,15 +22,14 @@ module RubyMemcheck
23
22
  def run_task(verbose)
24
23
  error = nil
25
24
 
26
- begin
25
+ @reporter = TestTaskReporter.new(configuration)
26
+ @reporter.run_ruby_with_valgrind do
27
27
  # RSpec::Core::RakeTask#run_task calls Kernel.exit on failure
28
28
  super
29
29
  rescue SystemExit => e
30
30
  error = e
31
31
  end
32
32
 
33
- report_valgrind_errors
34
-
35
33
  raise error if error
36
34
  end
37
35
 
@@ -40,7 +38,6 @@ module RubyMemcheck
40
38
  def spec_command
41
39
  # First part of command is Ruby
42
40
  args = super.split(" ")[1..]
43
- args.unshift("-r" + File.expand_path(File.join(__dir__, "../test_helper.rb")))
44
41
 
45
42
  configuration.command(args)
46
43
  end
@@ -4,30 +4,28 @@ module RubyMemcheck
4
4
  class Stack
5
5
  attr_reader :configuration, :frames
6
6
 
7
- def initialize(configuration, stack_xml)
7
+ def initialize(configuration, loaded_binaries, stack_xml)
8
8
  @configuration = configuration
9
- @frames = stack_xml.xpath("frame").map { |frame| Frame.new(configuration, frame) }
9
+ @frames = stack_xml.xpath("frame").map { |frame| Frame.new(configuration, loaded_binaries, frame) }
10
10
  end
11
11
 
12
12
  def skip?
13
13
  in_binary = false
14
14
 
15
15
  frames.each do |frame|
16
- fn = frame.fn
17
-
18
16
  if frame.in_ruby?
19
17
  # If a stack from from the binary was encountered first, then this
20
18
  # memory leak did not occur from Ruby
21
19
  unless in_binary
22
20
  # Skip this stack because it was called from Ruby
23
- return true if configuration.skipped_ruby_functions.any? { |r| r.match?(fn) }
21
+ return true if configuration.skipped_ruby_functions.any? { |r| r.match?(frame.fn) }
24
22
  end
25
23
  elsif frame.in_binary?
26
24
  in_binary = true
27
25
 
28
26
  # Skip the Init function because it is only ever called once, so
29
27
  # leaks in it cannot cause memory bloat
30
- return true if fn == "Init_#{configuration.binary_name}"
28
+ return true if frame.binary_init_func?
31
29
  end
32
30
  end
33
31
 
@@ -1,3 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- at_exit { GC.start }
3
+ at_exit do
4
+ File.open(ENV["RUBY_MEMCHECK_LOADED_FEATURES_FILE"], "w") do |f|
5
+ f.write($LOADED_FEATURES.join("\n"))
6
+ end
7
+
8
+ GC.start
9
+ end
@@ -2,9 +2,8 @@
2
2
 
3
3
  module RubyMemcheck
4
4
  class TestTask < Rake::TestTask
5
- include TestTaskReporter
6
-
7
5
  attr_reader :configuration
6
+ attr_reader :reporter
8
7
 
9
8
  def initialize(*args)
10
9
  @configuration =
@@ -18,10 +17,14 @@ module RubyMemcheck
18
17
  end
19
18
 
20
19
  def ruby(*args, **options, &block)
21
- args.unshift("-r" + File.expand_path(File.join(__dir__, "test_helper.rb")))
22
20
  command = configuration.command(args)
21
+
22
+ @reporter = TestTaskReporter.new(configuration)
23
+
24
+ @reporter.setup
25
+
23
26
  sh(command, **options) do |ok, res|
24
- report_valgrind_errors
27
+ @reporter.report_valgrind_errors
25
28
 
26
29
  yield ok, res if block_given?
27
30
  end
@@ -1,36 +1,62 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyMemcheck
4
- module TestTaskReporter
4
+ class TestTaskReporter
5
5
  VALGRIND_REPORT_MSG = "Valgrind reported errors (e.g. memory leak or use-after-free)"
6
6
 
7
+ attr_reader :configuration
7
8
  attr_reader :errors
8
9
 
9
- private
10
+ def initialize(configuration)
11
+ @configuration = configuration
12
+ @loaded_binaries = nil
13
+ end
14
+
15
+ def run_ruby_with_valgrind(&block)
16
+ setup
17
+ yield
18
+ report_valgrind_errors
19
+ end
20
+
21
+ def setup
22
+ ENV["RUBY_MEMCHECK_LOADED_FEATURES_FILE"] = File.expand_path(configuration.loaded_features_file)
23
+ ENV["RUBY_MEMCHECK_RUNNING"] = "1"
24
+ end
10
25
 
11
26
  def report_valgrind_errors
12
- if configuration.valgrind_xml_dir
13
- xml_files = valgrind_xml_files
14
- parse_valgrind_output(xml_files)
15
- remove_valgrind_xml_files(xml_files)
16
-
17
- unless errors.empty?
18
- output_valgrind_errors
19
- raise VALGRIND_REPORT_MSG
20
- end
27
+ parse_valgrind_output
28
+ remove_valgrind_xml_files
29
+
30
+ unless errors.empty?
31
+ output_valgrind_errors
32
+ raise VALGRIND_REPORT_MSG
21
33
  end
22
34
  end
23
35
 
36
+ private
37
+
38
+ def loaded_binaries
39
+ return @loaded_binaries if @loaded_binaries
40
+
41
+ loaded_features = File.readlines(configuration.loaded_features_file, chomp: true)
42
+ @loaded_binaries = loaded_features.keep_if do |feat|
43
+ # Keep only binaries (ignore Ruby files).
44
+ File.extname(feat) == ".so"
45
+ end.freeze
46
+
47
+ @loaded_binaries
48
+ end
49
+
24
50
  def valgrind_xml_files
25
- Dir[File.join(configuration.valgrind_xml_dir, "*")]
51
+ @valgrind_xml_files ||= Dir[File.join(configuration.temp_dir, "*.xml")].freeze
26
52
  end
27
53
 
28
- def parse_valgrind_output(xml_files)
54
+ def parse_valgrind_output
29
55
  require "nokogiri"
30
56
 
31
57
  @errors = []
32
58
 
33
- xml_files.each do |file|
59
+ valgrind_xml_files.each do |file|
34
60
  reader = Nokogiri::XML::Reader(File.open(file)) do |config| # rubocop:disable Style/SymbolProc
35
61
  config.huge
36
62
  end
@@ -38,7 +64,7 @@ module RubyMemcheck
38
64
  next unless node.name == "error" && node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT
39
65
 
40
66
  error_xml = Nokogiri::XML::Document.parse(node.outer_xml).root
41
- error = ValgrindError.new(configuration, error_xml)
67
+ error = ValgrindError.new(configuration, loaded_binaries, error_xml)
42
68
  next if error.skip?
43
69
 
44
70
  @errors << error
@@ -46,8 +72,8 @@ module RubyMemcheck
46
72
  end
47
73
  end
48
74
 
49
- def remove_valgrind_xml_files(xml_files)
50
- xml_files.each do |file|
75
+ def remove_valgrind_xml_files
76
+ valgrind_xml_files.each do |file|
51
77
  File.delete(file)
52
78
  end
53
79
  end
@@ -7,7 +7,7 @@ module RubyMemcheck
7
7
 
8
8
  attr_reader :kind, :msg, :stack, :suppression
9
9
 
10
- def initialize(configuration, error)
10
+ def initialize(configuration, loaded_binaries, error)
11
11
  @kind = error.at_xpath("kind").content
12
12
  @msg =
13
13
  if kind_leak?
@@ -15,7 +15,7 @@ module RubyMemcheck
15
15
  else
16
16
  error.at_xpath("what").content
17
17
  end
18
- @stack = Stack.new(configuration, error.at_xpath("stack"))
18
+ @stack = Stack.new(configuration, loaded_binaries, error.at_xpath("stack"))
19
19
  @configuration = configuration
20
20
 
21
21
  suppression_node = error.at_xpath("suppression")
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyMemcheck
4
- VERSION = "1.3.2"
4
+ VERSION = "2.0.1"
5
5
  end
data/lib/ruby_memcheck.rb CHANGED
@@ -19,11 +19,7 @@ module RubyMemcheck
19
19
  end
20
20
 
21
21
  def default_configuration
22
- unless @default_configuration
23
- raise "RubyMemcheck is not configured with a default configuration. "\
24
- "Please run RubyMemcheck.config before using it."
25
- end
26
- @default_configuration
22
+ @default_configuration ||= config
27
23
  end
28
24
  end
29
25
  end
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.email = ["peter@peterzhu.ca"]
10
10
 
11
11
  spec.summary = "Use Valgrind memcheck without going crazy"
12
- spec.homepage = "https://github.com/peterzhu2118/ruby_memcheck"
12
+ spec.homepage = "https://github.com/Shopify/ruby_memcheck"
13
13
  spec.license = "MIT"
14
14
  spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
15
15
 
@@ -12,13 +12,6 @@
12
12
  fun:require_internal
13
13
  ...
14
14
  }
15
- {
16
- Remove this after Ruby 2.7.7, 3.0.5, 3.1.3 are relased. See: https://github.com/Shopify/ruby_memcheck/issues/6
17
- Memcheck:Leak
18
- ...
19
- fun:stack_chunk_alloc
20
- ...
21
- }
22
15
  {
23
16
  recursive_list_access creates a hash called `list` that is stored on the threadptr_recursive_hash. This is reported as a memory leak.
24
17
  Memcheck:Leak
@@ -50,3 +43,20 @@
50
43
  fun:*try_statx*
51
44
  ...
52
45
  }
46
+ {
47
+ strscan_do_scan in strscan.c will sometimes replace the ptr of the regex, which can be reported as a memory leak if the regex is stored in an iseq. https://github.com/ruby/ruby/pull/8136
48
+ Memcheck:Leak
49
+ ...
50
+ fun:rb_reg_prepare_re
51
+ fun:strscan_do_scan
52
+ ...
53
+ }
54
+ {
55
+ The callcache table (RCLASS_CC_TBL) is lazily created, so it is allocated when the first method that gets cached. If this happens in a native extension, it may be reported as a memory leak.
56
+ Memcheck:Leak
57
+ ...
58
+ fun:rb_id_table_create
59
+ ...
60
+ fun:rb_callable_method_entry
61
+ ...
62
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_memcheck
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Zhu
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-17 00:00:00.000000000 Z
11
+ date: 2023-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -129,6 +129,7 @@ executables: []
129
129
  extensions: []
130
130
  extra_rdoc_files: []
131
131
  files:
132
+ - ".github/workflows/cla.yml"
132
133
  - ".github/workflows/lint.yml"
133
134
  - ".github/workflows/test.yml"
134
135
  - ".gitignore"
@@ -150,11 +151,11 @@ files:
150
151
  - lib/ruby_memcheck/version.rb
151
152
  - ruby_memcheck.gemspec
152
153
  - suppressions/ruby.supp
153
- homepage: https://github.com/peterzhu2118/ruby_memcheck
154
+ homepage: https://github.com/Shopify/ruby_memcheck
154
155
  licenses:
155
156
  - MIT
156
157
  metadata:
157
- homepage_uri: https://github.com/peterzhu2118/ruby_memcheck
158
+ homepage_uri: https://github.com/Shopify/ruby_memcheck
158
159
  post_install_message:
159
160
  rdoc_options: []
160
161
  require_paths: