ruby_memcheck 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +1 -1
- data/.rubocop.yml +3 -0
- data/README.md +20 -4
- data/lib/ruby_memcheck/configuration.rb +15 -4
- data/lib/ruby_memcheck/test_task_reporter.rb +2 -0
- data/lib/ruby_memcheck/version.rb +1 -1
- data/suppressions/ruby.supp +21 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4cd707ffa4ebdb25945d2d2654659a38c2272a0e73678d9c9f58e655e19b3cc6
|
4
|
+
data.tar.gz: df247c2a1e77374ad3c9521b1a3f2554c443fa80e33d50cd948727821a3267d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b4c337a38ad04be648365f4de828187524f11f67699aaa187182d906e4dbf922d84767003e4bab79572c0b3c41fe908c2bb23b1029b1d49360a9c399df5010f
|
7
|
+
data.tar.gz: 3c73f128a88b0eabce497b0ebb464166ccc541dbf5ec0e03b1951d8e1569abd6123a48a454b6a2e9b808c95770ea922b6e027db8c2be2a458d5f0b53f3cb74bc
|
data/.github/workflows/test.yml
CHANGED
@@ -6,9 +6,9 @@ jobs:
|
|
6
6
|
strategy:
|
7
7
|
matrix:
|
8
8
|
entry:
|
9
|
-
- { ruby: '2.6', allowed-failure: false }
|
10
9
|
- { ruby: '2.7', allowed-failure: false }
|
11
10
|
- { ruby: '3.0', allowed-failure: false }
|
11
|
+
- { ruby: '3.1', allowed-failure: false }
|
12
12
|
- { ruby: ruby-head, allowed-failure: false }
|
13
13
|
name: ruby ${{ matrix.entry.ruby }}
|
14
14
|
steps:
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -26,16 +26,19 @@ Only gems with native extensions can use this gem. If your gem is written in pla
|
|
26
26
|
|
27
27
|
This gem runs Valgrind with the `--xml` option to generate an XML of all the errors. It will then parse the XML and use various heuristics based on the type of the error and the stack trace to filter out errors that are false positives.
|
28
28
|
|
29
|
+
For more details, read [this blog post](https://blog.peterzhu.ca/ruby-memcheck/).
|
30
|
+
|
29
31
|
### Limitations
|
30
32
|
|
31
33
|
Because of the aggressive heuristics used to filter out false positives, there are various limitations of what this gem can detect.
|
32
34
|
|
33
35
|
1. This gem is only expected to work on Linux.
|
36
|
+
1. This gem runs your gem's test suite to find errors and memory leaks. It will only be able to report errors on code paths that are covered by your tests. So make sure your test suite has good coverage!
|
34
37
|
1. It will not find memory leaks in Ruby. It filters out everything in Ruby.
|
35
38
|
1. It will not find memory leaks of allocations that occurred in Ruby (even if the memory leak is caused by your native extension).
|
36
39
|
|
37
40
|
An example of this is if a string is allocated in Ruby, passed into your native extension, you change the pointer of the string without freeing the contents, so the contents of the string becomes leaked.
|
38
|
-
1. To filter out false
|
41
|
+
1. To filter out false positives, it will only find definite leaks (i.e. memory regions with no pointers to it). It will not find possible leaks (i.e. memory regions with pointers to it).
|
39
42
|
1. It will not find leaks that occur in the `Init` function of your native extension.
|
40
43
|
1. It will not find uses of undefined values (e.g. conditional jumps depending on undefined values). This is just a technical limitation that has not been solved yet (contributions welcome!).
|
41
44
|
|
@@ -67,6 +70,7 @@ The easiest way to use this gem is to use it on your test suite (minitest or RSp
|
|
67
70
|
```ruby
|
68
71
|
RubyMemcheck.config(binary_name: "your_binary_name")
|
69
72
|
```
|
73
|
+
|
70
74
|
1. Setup the test task for your test framework.
|
71
75
|
- **minitest**
|
72
76
|
|
@@ -105,18 +109,30 @@ The easiest way to use this gem is to use it on your test suite (minitest or RSp
|
|
105
109
|
For example, if your Rakefile looked like this before:
|
106
110
|
|
107
111
|
```ruby
|
108
|
-
|
112
|
+
RSpec::Core::RakeTask.new(spec: :compile)
|
109
113
|
```
|
110
114
|
|
111
115
|
You can change it to look like this:
|
112
116
|
|
113
117
|
```ruby
|
114
|
-
|
118
|
+
RSpec::Core::RakeTask.new(spec: :compile)
|
115
119
|
namespace :spec do
|
116
120
|
RubyMemcheck::RSpec::RakeTask.new(valgrind: :compile)
|
117
121
|
end
|
118
122
|
```
|
119
123
|
|
124
|
+
1. Add the following line to your `test_helper.rb` or `spec_helper.rb`:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
at_exit { GC.start }
|
128
|
+
```
|
129
|
+
|
130
|
+
This will run a major garbage collection cycle before the Ruby process shuts down. This will ensure that any remaining Ruby objects are collected which will prevent Valgrind from reporting false positives.
|
131
|
+
|
132
|
+
It is safest to add the line above at the very first line of `test_helper.rb` or `spec_helper.rb`.
|
133
|
+
|
134
|
+
- **For minitest:** It is important that the line above is added BEFORE the `require "minitest/autorun"` line.
|
135
|
+
|
120
136
|
1. You're ready to run your test suite with Valgrind using `rake test:valgrind` or `rake spec:valgrind`! Note that this will take a while to run because Valgrind will make Ruby significantly slower.
|
121
137
|
1. (Optional) If you find false positives in the output, you can create Valgrind suppression files. See the [`Suppression files`](#suppression-files) section for more details.
|
122
138
|
|
@@ -140,7 +156,7 @@ When you run `RubyMemcheck.config`, you are creating a default `RubyMemcheck::Co
|
|
140
156
|
|
141
157
|
If you find false positives in the output, you can create suppression files in a `suppressions` directory in the root directory of your gem. In this directory, you can create [Valgrind suppression files](https://wiki.wxwidgets.org/Valgrind_Suppression_File_Howto).
|
142
158
|
|
143
|
-
The most basic suppression file is `
|
159
|
+
The most basic suppression file is `ruby.supp`. If you want some suppressions for only specific versions of Ruby, you can add the Ruby version to the filename. For example, `ruby-3.supp` will suppress for any Rubies with a major version of 3 (e.g. 3.0.0, 3.1.1, etc.), while suppression file `ruby-3.1.supp` will only be used for Ruby with a major and minor version of 3.1 (e.g. 3.1.0, 3.1.1, etc.).
|
144
160
|
|
145
161
|
## Success stories
|
146
162
|
|
@@ -31,7 +31,7 @@ module RubyMemcheck
|
|
31
31
|
/\Arb_yield/,
|
32
32
|
].freeze
|
33
33
|
|
34
|
-
attr_reader :binary_name, :ruby, :valgrind, :valgrind_options, :
|
34
|
+
attr_reader :binary_name, :ruby, :valgrind, :valgrind_options, :valgrind_suppression_files,
|
35
35
|
:valgrind_generate_suppressions, :skipped_ruby_functions, :valgrind_xml_dir, :output_io
|
36
36
|
alias_method :valgrind_generate_suppressions?, :valgrind_generate_suppressions
|
37
37
|
|
@@ -50,7 +50,9 @@ module RubyMemcheck
|
|
50
50
|
@ruby = ruby
|
51
51
|
@valgrind = valgrind
|
52
52
|
@valgrind_options = valgrind_options
|
53
|
-
@
|
53
|
+
@valgrind_suppression_files =
|
54
|
+
get_valgrind_suppression_files(File.join(__dir__, "../../suppressions")) +
|
55
|
+
get_valgrind_suppression_files(valgrind_suppressions_dir)
|
54
56
|
@valgrind_generate_suppressions = valgrind_generate_suppressions
|
55
57
|
@skipped_ruby_functions = skipped_ruby_functions
|
56
58
|
@output_io = output_io
|
@@ -80,7 +82,7 @@ module RubyMemcheck
|
|
80
82
|
"ulimit -s unlimited && ",
|
81
83
|
valgrind,
|
82
84
|
valgrind_options,
|
83
|
-
|
85
|
+
valgrind_suppression_files.map { |f| "--suppressions=#{f}" },
|
84
86
|
valgrind_generate_suppressions ? "--gen-suppressions=all" : "",
|
85
87
|
ruby,
|
86
88
|
args,
|
@@ -90,13 +92,22 @@ module RubyMemcheck
|
|
90
92
|
private
|
91
93
|
|
92
94
|
def get_valgrind_suppression_files(dir)
|
95
|
+
dir = File.expand_path(dir)
|
96
|
+
|
93
97
|
full_ruby_version = "#{RUBY_ENGINE}-#{RUBY_VERSION}.#{RUBY_PATCHLEVEL}"
|
94
98
|
versions = [full_ruby_version]
|
95
99
|
(0..3).reverse_each { |i| versions << full_ruby_version.split(".")[0, i].join(".") }
|
96
100
|
versions << RUBY_ENGINE
|
97
101
|
|
98
102
|
versions.map do |version|
|
99
|
-
Dir[File.join(dir, "#{binary_name}_#{version}.supp")]
|
103
|
+
old_format_files = Dir[File.join(dir, "#{binary_name}_#{version}.supp")]
|
104
|
+
|
105
|
+
unless old_format_files.empty?
|
106
|
+
warn("ruby_memcheck: please migrate your suppression filenames from " \
|
107
|
+
"`gem_name_ruby-3.1.0.supp` to `ruby-3.1.0.supp` (drop the gem name from the filename)")
|
108
|
+
end
|
109
|
+
|
110
|
+
old_format_files + Dir[File.join(dir, "#{version}.supp")]
|
100
111
|
end.flatten
|
101
112
|
end
|
102
113
|
end
|
@@ -33,9 +33,11 @@ module RubyMemcheck
|
|
33
33
|
xml_files.each do |file|
|
34
34
|
Nokogiri::XML::Reader(File.open(file)).each do |node|
|
35
35
|
next unless node.name == "error" && node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT
|
36
|
+
|
36
37
|
error_xml = Nokogiri::XML::Document.parse(node.outer_xml).root
|
37
38
|
error = ValgrindError.new(configuration, error_xml)
|
38
39
|
next if error.skip?
|
40
|
+
|
39
41
|
@errors << error
|
40
42
|
end
|
41
43
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
{
|
2
|
+
On platforms where memcpy is safe for overlapped memory, the compiler will sometimes replace memmove with memcpy. Valgrind may report a false positive.
|
3
|
+
Memcheck:Overlap
|
4
|
+
fun:__memcpy_chk
|
5
|
+
fun:memmove
|
6
|
+
...
|
7
|
+
}
|
8
|
+
{
|
9
|
+
Requiring a file will add it to the loaded features, which may be reported as a leak.
|
10
|
+
Memcheck:Leak
|
11
|
+
...
|
12
|
+
fun:require_internal
|
13
|
+
...
|
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
|
+
}
|
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.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Zhu
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-10-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -148,6 +148,7 @@ files:
|
|
148
148
|
- lib/ruby_memcheck/valgrind_error.rb
|
149
149
|
- lib/ruby_memcheck/version.rb
|
150
150
|
- ruby_memcheck.gemspec
|
151
|
+
- suppressions/ruby.supp
|
151
152
|
homepage: https://github.com/peterzhu2118/ruby_memcheck
|
152
153
|
licenses:
|
153
154
|
- MIT
|
@@ -168,7 +169,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
169
|
- !ruby/object:Gem::Version
|
169
170
|
version: '0'
|
170
171
|
requirements: []
|
171
|
-
rubygems_version: 3.
|
172
|
+
rubygems_version: 3.3.7
|
172
173
|
signing_key:
|
173
174
|
specification_version: 4
|
174
175
|
summary: Use Valgrind memcheck without going crazy
|