https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112020-12-31T12:04:50ZRuby Issue Tracking SystemRuby master - Bug #17494: ruby is hanged when using activesupport + rspec + rspec-parameterizedhttps://bugs.ruby-lang.org/issues/17494?journal_id=896662020-12-31T12:04:50Zsue445 (Go Sueyoshi)
<ul><li><strong>Subject</strong> changed from <i>ruby is hunged when using activesupport + rspec + rspec-parameterized</i> to <i>ruby is hanged when using activesupport + rspec + rspec-parameterized</i></li></ul> Ruby master - Bug #17494: ruby is hanged when using activesupport + rspec + rspec-parameterizedhttps://bugs.ruby-lang.org/issues/17494?journal_id=896802021-01-01T07:34:40Zyahonda (Yasuo Honda)yasuo.honda@gmail.com
<ul></ul><p>Looks like this behavior has been triggered by <a href="https://github.com/ruby/ruby/commit/b9007b6c548f91e88fd3f2ffa23de740431fa969" class="external">https://github.com/ruby/ruby/commit/b9007b6c548f91e88fd3f2ffa23de740431fa969</a></p>
<ul>
<li>Created one file repro named <code>rep17494.rb</code> by adding <code>require "rspec/autorun"</code>
</li>
</ul>
<pre><code>require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
gem "activesupport", "6.1.0"
gem "rspec", "3.10.0"
gem "rspec-parameterized", "0.4.2"
end
require "rspec/autorun"
require "active_support/all"
require "rspec-parameterized"
describe "CLI" do
subject do
# Expected error, but actual hunged here
cli.foo # <- hunged here
end
it { expect { subject }.to raise_error }
end
describe "GitlabMrRelease::Project" do
describe "#api_version" do
using RSpec::Parameterized::TableSyntax
where(:api_endpoint, :expected) do
"http://example.com/api/v4/" | 4
end
with_them do
# it { should eq expected }
end
end
end
</code></pre>
<ul>
<li>Execute rep17494.rb script against Ruby as of f2286925f08406bc857f7b03ad6779a5d61443ae which is the parent commit of b9007b6c548f91e88fd3f2ffa23de740431fa969</li>
</ul>
<pre><code>$ docker run -it --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp rubylang/rubyfarm:f2286925f08406bc857f7b03ad6779a5d61443ae ruby rep17494.rb
</code></pre>
<p>It works as expected <code>1 example, 0 failures</code>.</p>
<ul>
<li>Execute rep17494.rb script against Ruby as of b9007b6c548f91e88fd3f2ffa23de740431fa969</li>
</ul>
<pre><code>$ docker run -it --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp rubylang/rubyfarm:b9007b6c548f91e88fd3f2ffa23de740431fa969 ruby rep17494.rb
</code></pre>
<p>It hangs.</p>
<p>Of course, this reproduce case does not require Docker if you can build Ruby as of each commit.</p> Ruby master - Bug #17494: ruby is hanged when using activesupport + rspec + rspec-parameterizedhttps://bugs.ruby-lang.org/issues/17494?journal_id=900372021-01-22T05:41:23Zsue445 (Go Sueyoshi)
<ul></ul><a name="Workaround"></a>
<h1 >Workaround<a href="#Workaround" class="wiki-anchor">¶</a></h1>
<p><code>require</code> only minimal files.</p>
<p>In this case, stop to require "active_support/all"</p>
<p>e.g.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># require "active_support/all"</span>
<span class="nb">require</span> <span class="s2">"active_support/core_ext/time/zones"</span>
<span class="nb">require</span> <span class="s2">"active_support/core_ext/array/wrap"</span>
<span class="nb">require</span> <span class="s2">"active_support/core_ext/hash/keys"</span>
<span class="nb">require</span> <span class="s2">"active_support/core_ext/time/calculations"</span>
</code></pre> Ruby master - Bug #17494: ruby is hanged when using activesupport + rspec + rspec-parameterizedhttps://bugs.ruby-lang.org/issues/17494?journal_id=900402021-01-22T16:32:47Zalpaca-tc (Hiroyuki Ishii)
<ul></ul><p>I investigated this issue deeply based on yhonda's example code. Then I succeeded to create tiny reproduction code.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Object</span><span class="p">.</span><span class="nf">prepend</span><span class="p">(</span><span class="no">Module</span><span class="p">.</span><span class="nf">new</span><span class="p">)</span>
<span class="n">using</span><span class="p">(</span><span class="no">Module</span><span class="p">.</span><span class="nf">new</span> <span class="p">{</span>
<span class="n">refine</span> <span class="no">Object</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">hello</span><span class="p">;</span> <span class="k">end</span>
<span class="k">end</span>
<span class="p">})</span>
<span class="no">Object</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">hello</span>
<span class="k">module</span> <span class="nn">M</span>
<span class="k">def</span> <span class="nf">hello</span><span class="p">;</span> <span class="k">end</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">A</span>
<span class="kp">include</span> <span class="no">M</span>
<span class="k">end</span>
<span class="no">Object</span><span class="p">.</span><span class="nf">instance_methods</span> <span class="c1">#=> hanged!!!</span>
</code></pre> Ruby master - Bug #17494: ruby is hanged when using activesupport + rspec + rspec-parameterizedhttps://bugs.ruby-lang.org/issues/17494?journal_id=900802021-01-25T00:42:08Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<ul></ul><p><a class="user active user-mention" href="https://bugs.ruby-lang.org/users/10641">@alpaca-tc (Hiroyuki Ishii)</a> Thannk you, I can reproduce that too.</p>
<pre><code>zsh % LC_ALL=C gdb --args ./miniruby ~/tmp.rb
GNU gdb (Ubuntu 8.2-0ubuntu1~18.04) 8.2
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./miniruby...done.
(gdb) run
Starting program: /miniruby /tmp.rb
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
# <<<<< Hangs
^C
Program received signal SIGINT, Interrupt.
0x0000555555844e8f in hash_table_index (tbl=0x555555cdfcf0, key=1942) at id_table.c:132
132 if (tbl->capa > 0) {
(gdb) bt
#0 0x0000555555844e8f in hash_table_index (tbl=0x555555cdfcf0, key=1942) at id_table.c:132
#1 0x0000555555844e0c in rb_id_table_lookup (tbl=0x555555cdfcf0, id=31073, valp=0x7fffffff99a0) at id_table.c:230
#2 0x00005555558b42ae in lookup_method_table (klass=93824999686600, id=31073) at vm_method.c:701
#3 0x00005555558b6dc4 in search_method (klass=93824999686600, id=31073, defined_class_ptr=0x0) at vm_method.c:981
#4 0x00005555558b4ff5 in search_method_protect (klass=93824999686544, id=31073, defined_class_ptr=0x0) at vm_method.c:997
#5 0x00005555558b5f80 in resolve_refined_method (refinements=8, me=0x555555c6ba08, defined_class_ptr=0x0) at vm_method.c:1267
#6 0x00005555558b5e31 in rb_resolve_refined_method (refinements=8, me=0x555555c6be30) at vm_method.c:1275
#7 0x00005555555cbb56 in method_entry_i (key=31073, value=93824999669296, data=0x7fffffff9bb8) at class.c:1372
#8 0x00005555558452d8 in rb_id_table_foreach (tbl=0x555555dce520, func=0x5555555cbb00 <method_entry_i>, data=0x7fffffff9bb8) at id_table.c:299
#9 0x00005555555ce5b4 in add_instance_method_list (mod=93825000677184, me_arg=0x7fffffff9bb8) at class.c:1393
#10 0x00005555555cb040 in class_instance_method_list (argc=0, argv=0x7ffff7ecb048, mod=93825000677184, obj=0, func=0x5555555cb0e0 <ins_methods_i>) at class.c:1429
#11 0x00005555555caf1c in rb_class_instance_methods (argc=0, argv=0x7ffff7ecb048, mod=93825000677184) at class.c:1470
#12 0x00005555558e3cea in ractor_safe_call_cfunc_m1 (recv=93825000677184, argc=0, argv=0x7ffff7ecb048, func=0x5555555caef0 <rb_class_instance_methods>) at vm_insnhelper.c:2706
#13 0x00005555558deba5 in vm_call_cfunc_with_frame (ec=0x555555c567d0, reg_cfp=0x7ffff7fcaf90, calling=0x7fffffffa020) at vm_insnhelper.c:2896
#14 0x00005555558d7830 in vm_call_cfunc (ec=0x555555c567d0, reg_cfp=0x7ffff7fcaf90, calling=0x7fffffffa020) at vm_insnhelper.c:2917
#15 0x00005555558d71c4 in vm_call_method_each_type (ec=0x555555c567d0, cfp=0x7ffff7fcaf90, calling=0x7fffffffa020) at vm_insnhelper.c:3386
#16 0x00005555558d6cb2 in vm_call_method (ec=0x555555c567d0, cfp=0x7ffff7fcaf90, calling=0x7fffffffa020) at vm_insnhelper.c:3479
#17 0x00005555558b9205 in vm_call_general (ec=0x555555c567d0, reg_cfp=0x7ffff7fcaf90, calling=0x7fffffffa020) at vm_insnhelper.c:3522
#18 0x00005555558cdbc1 in vm_sendish (ec=0x555555c567d0, reg_cfp=0x7ffff7fcaf90, cd=0x555555dcd6d0, block_handler=0, method_explorer=mexp_search_method) at vm_insnhelper.c:4497
#19 0x00005555558a0dbe in vm_exec_core (ec=0x555555c567d0, initial=0) at insns.def:789
#20 0x00005555558c306e in rb_vm_exec (ec=0x555555c567d0, mjit_enable_p=true) at vm.c:2162
#21 0x00005555558c42a0 in rb_iseq_eval_main (iseq=0x555555c708c8) at vm.c:2419
#22 0x0000555555656757 in rb_ec_exec_node (ec=0x555555c567d0, n=0x555555c708c8) at eval.c:317
#23 0x000055555565659c in ruby_run_node (n=0x555555c708c8) at eval.c:375
#24 0x000055555557ce44 in main (argc=2, argv=0x7fffffffc928) at main.c:47
(gdb)
</code></pre>
<p>Edit: updated the backtrace using <code>-O0</code> binary.</p> Ruby master - Bug #17494: ruby is hanged when using activesupport + rspec + rspec-parameterizedhttps://bugs.ruby-lang.org/issues/17494?journal_id=900812021-01-25T08:51:28Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul></ul><p>This patch seems to avoid the loop for the time being.</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git i/class.c w/class.c
index a62ae669f84..61f3ece40f4 100644
</span><span class="gd">--- i/class.c
</span><span class="gi">+++ w/class.c
</span><span class="p">@@ -1369,7 +1369,7 @@</span> method_entry_i(ID key, VALUE value, void *data)
if (me->def->type == VM_METHOD_TYPE_REFINED) {
VALUE owner = me->owner;
<span class="gd">- me = rb_resolve_refined_method(Qnil, me);
</span><span class="gi">+ me = rb_method_entry_with_refinements(owner, me->called_id, NULL);
</span> if (!me) return ID_TABLE_CONTINUE;
if (!arg->recur && me->owner != owner) return ID_TABLE_CONTINUE;
}
</code></pre> Ruby master - Bug #17494: ruby is hanged when using activesupport + rspec + rspec-parameterizedhttps://bugs.ruby-lang.org/issues/17494?journal_id=900932021-01-26T00:45:44Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul></ul><p>The previous patch failed an assertion.<br>
<a href="https://github.com/nobu/ruby/runs/1760739746?check_suite_focus=true#step:15:288" class="external">https://github.com/nobu/ruby/runs/1760739746?check_suite_focus=true#step:15:288</a></p>
<blockquote>
<p>| Assertion Failed: ../src/vm_method.c:990:search_method:me == NULL || !METHOD_ENTRY_INVALIDATED(me)</p>
</blockquote>
<p>Maybe the real cause is an access to the invalidated method entry?</p> Ruby master - Bug #17494: ruby is hanged when using activesupport + rspec + rspec-parameterizedhttps://bugs.ruby-lang.org/issues/17494?journal_id=900992021-01-26T05:32:20Zyahonda (Yasuo Honda)yasuo.honda@gmail.com
<ul></ul><p>This minimum case hangs since <a href="https://github.com/ruby/ruby/commit/b9007b6c548f91e88fd3f2ffa23de740431fa969" class="external">https://github.com/ruby/ruby/commit/b9007b6c548f91e88fd3f2ffa23de740431fa969</a></p>
<ul>
<li>Save this minimum case as <code>rep17494_min.rb</code>, added some p method to see if it hangs or not.</li>
</ul>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Object</span><span class="p">.</span><span class="nf">prepend</span><span class="p">(</span><span class="no">Module</span><span class="p">.</span><span class="nf">new</span><span class="p">)</span>
<span class="n">using</span><span class="p">(</span><span class="no">Module</span><span class="p">.</span><span class="nf">new</span> <span class="p">{</span>
<span class="n">refine</span> <span class="no">Object</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">hello</span><span class="p">;</span> <span class="k">end</span>
<span class="k">end</span>
<span class="p">})</span>
<span class="no">Object</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">hello</span>
<span class="k">module</span> <span class="nn">M</span>
<span class="k">def</span> <span class="nf">hello</span><span class="p">;</span> <span class="k">end</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">A</span>
<span class="kp">include</span> <span class="no">M</span>
<span class="k">end</span>
<span class="nb">p</span> <span class="s1">'Showing Object.instance_methods'</span>
<span class="nb">p</span> <span class="no">Object</span><span class="p">.</span><span class="nf">instance_methods</span>
</code></pre>
<ul>
<li>Run this rep17494_min.rb against as of b9007b6c548f91e88fd3f2ffa23de740431fa969 using <code>rubylang/rubyfarm:b9007b6c548f91e88fd3f2ffa23de740431fa969</code> docker image</li>
</ul>
<pre><code>% docker run -it --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp rubylang/rubyfarm:b9007b6c548f91e88fd3f2ffa23de740431fa969 ruby rep17494_min.rb
"Showing Object.instance_methods"
</code></pre>
<p>It hangs at <code>p Object.instance_methods</code>.</p>
<ul>
<li>Run this rep17494_min.rb against as of f2286925f08406bc857f7b03ad6779a5d61443ae, which is the parent commit of b9007b6c548f91e88fd3f2ffa23de740431fa969</li>
</ul>
<pre><code>% docker run -it --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp rubylang/rubyfarm:f2286925f08406bc857f7b03ad6779a5d61443ae ruby rep17494_min.rb
"Showing Object.instance_methods"
[:dup, :itself, :yield_self, :then, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :frozen?, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :singleton_class, :clone, :public_send, :method, :public_method, :singleton_method, :define_singleton_method, :extend, :<=>, :to_enum, :enum_for, :===, :=~, :!~, :nil?, :eql?, :respond_to?, :freeze, :inspect, :object_id, :send, :to_s, :display, :class, :hash, :__send__, :!, :__id__, :==, :!=, :equal?, :instance_eval, :instance_exec]
</code></pre>
<p>It shows the result of <code>p Object.instance_methods</code>.<br>
These steps do not require Docker if each Ruby build is available locally.</p> Ruby master - Bug #17494: ruby is hanged when using activesupport + rspec + rspec-parameterizedhttps://bugs.ruby-lang.org/issues/17494?journal_id=908732021-03-11T00:01:09Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul></ul><p>One possible workaround for this is a checking for an immediate loop in <code>resolve_refined_method</code>:</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/vm_method.c b/vm_method.c
index 2573e708ba..ebfe686a27 100644
</span><span class="gd">--- a/vm_method.c
</span><span class="gi">+++ b/vm_method.c
</span><span class="p">@@ -1245,7 +1245,7 @@</span> resolve_refined_method(VALUE refinements, const rb_method_entry_t *me, VALUE *de
{
while (me && me->def->type == VM_METHOD_TYPE_REFINED) {
VALUE refinement;
<span class="gd">- const rb_method_entry_t *tmp_me;
</span><span class="gi">+ const rb_method_entry_t *tmp_me, *prev_me = me;
</span> VALUE super;
<span class="err">
</span> refinement = find_refinement(refinements, me->owner);
<span class="p">@@ -1269,6 +1269,9 @@</span> resolve_refined_method(VALUE refinements, const rb_method_entry_t *me, VALUE *de
}
<span class="err">
</span> me = search_method_protect(super, me->called_id, defined_class_ptr);
<span class="gi">+ if (me == prev_me) {
+ return 0;
+ }
</span> }
return me;
}
</code></pre>
<p>This fixes the case in the example, but maybe there are other more complex cases that it wouldn't catch. However, even if it won't catch all cases, until we have solved the underlying issue, this seems like a reasonable thing to add. I can submit a pull request for this if other committers are in favor.</p> Ruby master - Bug #17494: ruby is hanged when using activesupport + rspec + rspec-parameterizedhttps://bugs.ruby-lang.org/issues/17494?journal_id=927212021-07-01T21:44:13Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Closed</i></li><li><strong>Backport</strong> changed from <i>2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN</i> to <i>2.6: DONTNEED, 2.7: DONTNEED, 3.0: REQUIRED</i></li></ul><p>This issue has been fixed in the master branch. I bisected the fixing commit to <a class="changeset" title="Method cache: fix refinement entry handling To invalidate some callable method entries, we repla..." href="https://bugs.ruby-lang.org/projects/ruby-master/repository/git/revisions/39a2ba5cc559900c30c3143da32446c2f20a7484">39a2ba5cc559900c30c3143da32446c2f20a7484</a>. This issue exists in Ruby 3.0 but not in Ruby 2.7 or 2.6, so if possible, this should be backported to 3.0.</p> Ruby master - Bug #17494: ruby is hanged when using activesupport + rspec + rspec-parameterizedhttps://bugs.ruby-lang.org/issues/17494?journal_id=927382021-07-03T03:15:13Znagachika (Tomoyuki Chikanaga)nagachika00@gmail.com
<ul><li><strong>Backport</strong> changed from <i>2.6: DONTNEED, 2.7: DONTNEED, 3.0: REQUIRED</i> to <i>2.6: DONTNEED, 2.7: DONTNEED, 3.0: DONE</i></li></ul><p>Thank you for your investigations.<br>
39a2ba5cc559900c30c3143da32446c2f20a7484 was already backported at d47df50678b00bd622e6be474031204ed2e52b31.<br>
See <a href="https://bugs.ruby-lang.org/issues/17806" class="external">https://bugs.ruby-lang.org/issues/17806</a> too.<br>
I will fill the Backport field with "3.0: DONE".</p>