Ruby Issue Tracking System: Issueshttps://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112024-03-14T10:17:44ZRuby Issue Tracking System
Redmine Ruby master - Misc #20336 (Open): DevMeeting-2024-04-17https://redmine.ruby-lang.org/issues/203362024-03-14T10:17:44Zmame (Yusuke Endoh)mame@ruby-lang.org
<a name="The-next-dev-meeting"></a>
<h1 >The next dev meeting<a href="#The-next-dev-meeting" class="wiki-anchor">¶</a></h1>
<p><strong>Date: 2024/04/17 13:00-17:00</strong> (JST)<br>
Log: <em>TBD</em></p>
<ul>
<li>Dev meeting <em>IS NOT</em> a decision-making place. All decisions should be done at the bug tracker.</li>
<li>Dev meeting is a place we can ask Matz, nobu, nurse and other developers directly.</li>
<li>Matz is a very busy person. Take this opportunity to ask him. If you can not attend, other attendees can ask instead of you (if attendees can understand your issue).</li>
<li>We will write a record of the discussion in the file or to each ticket in English.</li>
<li>All activities are best-effort (keep in mind that most of us are volunteer developers).</li>
<li>The date, time and place of the meeting are scheduled according to when/where we can reserve Matz's time.</li>
<li>
<em>DO NOT</em> discuss then on this ticket, please.</li>
</ul>
<a name="Call-for-agenda-items"></a>
<h1 >Call for agenda items<a href="#Call-for-agenda-items" class="wiki-anchor">¶</a></h1>
<p>If you have a ticket that you want matz and committers to discuss, please post it into this ticket in the following format:</p>
<pre><code>* [Ticket ref] Ticket title (your name)
* Comment (A summary of the ticket, why you put this ticket here, what point should be discussed, etc.)
</code></pre>
<p>Example:</p>
<pre><code>* [Feature #14609] `Kernel#p` without args shows the receiver (ko1)
* I feel this feature is very useful and some people say :+1: so let discuss this feature.
</code></pre>
<ul>
<li>It is recommended to add a comment by 2024/04/14. We hold a preparatory meeting to create an agenda a few days before the dev-meeting.</li>
<li>The format is strict. We'll use <a href="https://gist.github.com/mame/b0390509ce1491b43610b9ebb665eb86" class="external">this script to automatically create an markdown-style agenda</a>. We may ignore a comment that does not follow the format.</li>
<li>Your comment is mandatory. We cannot read all discussion of the ticket in a limited time. We appreciate it if you could write a short summary and update from a previous discussion.</li>
</ul> Ruby master - Bug #20314 (Open): Simultaneous Timeout expires may raise an exception after the blockhttps://redmine.ruby-lang.org/issues/203142024-02-29T06:25:26Zmame (Yusuke Endoh)mame@ruby-lang.org
<p>Launchable reports <code>TestTimeout#test_nested_timeout</code> as a flaky test, and I reproduced it as follows.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s2">"timeout"</span>
<span class="k">class</span> <span class="nc">A</span> <span class="o"><</span> <span class="no">Exception</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">B</span> <span class="o"><</span> <span class="no">Exception</span>
<span class="k">end</span>
<span class="k">begin</span>
<span class="no">Timeout</span><span class="p">.</span><span class="nf">timeout</span><span class="p">(</span><span class="mf">0.1</span><span class="p">,</span> <span class="no">A</span><span class="p">)</span> <span class="k">do</span>
<span class="no">Timeout</span><span class="p">.</span><span class="nf">timeout</span><span class="p">(</span><span class="mf">0.1</span><span class="p">,</span> <span class="no">B</span><span class="p">)</span> <span class="k">do</span>
<span class="kp">nil</span> <span class="k">while</span> <span class="kp">true</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">rescue</span> <span class="no">A</span><span class="p">,</span> <span class="no">B</span>
<span class="nb">p</span> <span class="vg">$!</span> <span class="c1">#=> #<A: execution expired></span>
<span class="c1"># Exception B is raised after the above call returns</span>
<span class="c1">#=> test.rb:16:in `p': execution expired (B)</span>
<span class="nb">p</span> <span class="ss">:end</span> <span class="c1"># not reach</span>
<span class="k">end</span>
</code></pre>
<p>This is because the timer thread performs two consecutive <code>Thread#raise</code> to the target thread.</p>
<p>I have discussed this with <a class="user active user-mention" href="https://redmine.ruby-lang.org/users/17">@ko1 (Koichi Sasada)</a> and have come up with three solutions.</p>
<a name="Solution-1"></a>
<h3 >Solution 1<a href="#Solution-1" class="wiki-anchor">¶</a></h3>
<p>When multiple nested Timeouts expire simultaneously, raise an exception for the outer-most Timeout and let the inner Timeouts expire without throwing an exception. In the above example, it would only raise A.</p>
<p>The problem with this approach is that if you are rescuing A in the inner block, it may never ends:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Timeout</span><span class="p">.</span><span class="nf">timeout</span><span class="p">(</span><span class="mf">0.1</span><span class="p">,</span> <span class="no">A</span><span class="p">)</span> <span class="k">do</span>
<span class="no">Timeout</span><span class="p">.</span><span class="nf">timeout</span><span class="p">(</span><span class="mf">0.1</span><span class="p">,</span> <span class="no">B</span><span class="p">)</span> <span class="k">do</span>
<span class="k">begin</span>
<span class="nb">sleep</span>
<span class="k">rescue</span> <span class="no">A</span>
<span class="nb">sleep</span> <span class="c1"># The exception A is caught. The inner Timeout is already expired, so the code (may) never end.</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>Note that, if A and B did not occur at the same time, it would raise B. This is a race condition.</p>
<a name="Solution-2"></a>
<h3 >Solution 2<a href="#Solution-2" class="wiki-anchor">¶</a></h3>
<p>When multiple nested Timeouts expire simultaneously, raise an exception for the inner-most Timeout and let the outer Timeouts wait until the inner-most Timeout returns. In the above example, it would raise either A or B, not both.</p>
<p>The problem with this approach is that if you are rescuing B in the inner block, it never ends:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Timeout</span><span class="p">.</span><span class="nf">timeout</span><span class="p">(</span><span class="mf">0.1</span><span class="p">,</span> <span class="no">A</span><span class="p">)</span> <span class="k">do</span>
<span class="no">Timeout</span><span class="p">.</span><span class="nf">timeout</span><span class="p">(</span><span class="mf">0.1</span><span class="p">,</span> <span class="no">B</span><span class="p">)</span> <span class="k">do</span>
<span class="k">begin</span>
<span class="nb">sleep</span>
<span class="k">rescue</span> <span class="no">B</span>
<span class="nb">sleep</span> <span class="c1"># The outer Timeout waits for the inner timeout, and the inner Timeout never return. So this code never ends.</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<a name="Solution-3"></a>
<h3 >Solution 3<a href="#Solution-3" class="wiki-anchor">¶</a></h3>
<p>Make thread interrupt queue one length. If the target thread has already been <code>Thread#raise(A)</code>, the new <code>Thread#raise(B)</code> blocks until the target thread processes A.</p>
<p>Since there will be no more simultaneous Thread#raise, there will be no more exceptions after the end of the block. The timeout timer thread should be changed in consideration that <code>Thread#raise</code> may block.</p> Ruby master - Feature #19430 (Open): Contribution wanted: DNS lookup by c-ares libraryhttps://redmine.ruby-lang.org/issues/194302023-02-10T05:23:29Zmame (Yusuke Endoh)mame@ruby-lang.org
<a name="Problem"></a>
<h2 >Problem<a href="#Problem" class="wiki-anchor">¶</a></h2>
<p>At the present time, Ruby uses <code>getaddrinfo(3)</code> to resolve names. Because this function is synchronous, we cannot interrupt the thread performing name resolution until the DNS server returns a response.</p>
<p>We can see this behavior by setting blackhole.webpagetest.org (72.66.115.13) as a DNS server, which swallows all packets, and resolving any name:</p>
<pre><code># cat /etc/resolv.conf
nameserver 72.66.115.13
# ./local/bin/ruby -rsocket -e 'Addrinfo.getaddrinfo("www.ruby-lang.org", 80)'
^C^C^C^C
</code></pre>
<p>As we see, Ctrl+C does not stop ruby.</p>
<p>The current workaround that users can take is to do name resolution in a Ruby thread.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="p">{</span> <span class="no">Addrinfo</span><span class="p">.</span><span class="nf">getaddrinfo</span><span class="p">(</span><span class="s2">"www.ruby-lang.org"</span><span class="p">,</span> <span class="mi">80</span><span class="p">)</span> <span class="p">}.</span><span class="nf">value</span>
</code></pre>
<p>The thread that calls this code is interruptible. (Note that the newly created thread itself will be stuck until the DNS lookup exceeds the time out.)</p>
<a name="Proposal"></a>
<h2 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h2>
<p>We can solve this problem by using c-ares, which is an asynchronous name resolver, as a backend of <code>Addrinfo.getaddrinfo</code>, etc. (<a class="user active user-mention" href="https://redmine.ruby-lang.org/users/1146">@sorah (Sorah Fukumori)</a> told me about this library, thanks!)</p>
<p><a href="https://c-ares.org/" class="external">https://c-ares.org/</a></p>
<p>I have created a PoC patch.</p>
<p><a href="https://github.com/mame/ruby/commit/547806146993bbc25984011d423dcc0f913b211c" class="external">https://github.com/mame/ruby/commit/547806146993bbc25984011d423dcc0f913b211c</a></p>
<p>By applying this patch, we can interrupt <code>Addrinfo.getaddrinfo</code> by Ctrl+C.</p>
<pre><code># cat /etc/resolv.conf
nameserver 72.66.115.13
# ./local/bin/ruby -rsocket -e 'Addrinfo.getaddrinfo("www.ruby-lang.org", 80)'
^C-e:1:in `getaddrinfo': Interrupt
from -e:1:in `<main>'
</code></pre>
<a name="Discussion"></a>
<h2 >Discussion<a href="#Discussion" class="wiki-anchor">¶</a></h2>
<a name="About-c-ares"></a>
<h3 >About c-ares<a href="#About-c-ares" class="wiki-anchor">¶</a></h3>
<p>According to the site of c-ares, some major tools including libcurl, Wireshark, and Apache Arrow are already using c-ares. In the language interpreter, node.js seems to be using c-ares.</p>
<p>I am honestly not sure about the compatibility of c-ares with <code>getaddrinfo(3)</code>. I guess there is no major incompatibility because I have not experienced any name resolution problem of curl. <a class="user active user-mention" href="https://redmine.ruby-lang.org/users/271">@akr (Akira Tanaka)</a> (who is the author and maintainer of Ruby's socket library) suggested to check if OS-specific name resolution, e.g., WINS on Windows, NIS on Solaris, etc., is supported. He also said that it may be acceptable even if they are not supported.</p>
<p>Whether to bundle c-ares source code with ruby would require further discussion. If this proposal is accepted, then c-ares will become a de facto essential dependency for practical use, like gmp, in my opinion. Incidentally, node.js bundles c-ares: <a href="https://github.com/nodejs/node/tree/main/deps/cares" class="external">https://github.com/nodejs/node/tree/main/deps/cares</a></p>
<a name="Alternative-approaches"></a>
<h3 >Alternative approaches<a href="#Alternative-approaches" class="wiki-anchor">¶</a></h3>
<p>Recent glibc provides <code>getaddrinfo_a(3)</code> which performs asynchronous name resolution. However, this function has a fatal problem of being incompatible with <code>fork(2)</code>, which is heavily used in the Ruby ecosystem. In fact, the attempt to use <code>getaddrinfo_a(3)</code> (<a class="issue tracker-2 status-1 priority-4 priority-default" title="Feature: Add resolv_timeout to TCPSocket (Open)" href="https://redmine.ruby-lang.org/issues/17134">#17134</a>) has been revert because it fails rails tests. (<a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Rails Active Job integration test fails with Ruby 3.0.0 since 2038cc6cab6ceeffef3ec3a765c70ae684f... (Closed)" href="https://redmine.ruby-lang.org/issues/17220">#17220</a>)</p>
<p>Another alternative is to have a worker pthread inside Ruby that calls getaddrinfo(3). Instead of calling getaddrinfo(3) directly, <code>Addrinfo.getaddrinfo</code> would ask the worker to resolve a name and wait for a response. This method should be able to implement cancellation. (Simply put, this means reimplementation of getaddrinfo_a(3) on our own, taking into account of `fork(2).)</p>
<p>This has the advantages: not adding dependencies on external libraries and not having compatibility issues with <code>getaddrinfo(3)</code>. However, it is considerably more difficult to implement and maintain. An internal pthread may have a non-trivial impact on the execution efficiency and memory usage. Also, we may need to implement a mechanism to dynamically change the number of workers depending on the load.</p>
<p>It would be ideal if we could try and evaluate both approaches. But my current impression is that using c-ares is the quickest and best compromise.</p>
<a name="Contribution-wanted"></a>
<h2 >Contribution wanted<a href="#Contribution-wanted" class="wiki-anchor">¶</a></h2>
<p>I have made it up to the PoC, but don't have much time to complete this. <a class="user active user-mention" href="https://redmine.ruby-lang.org/users/5">@naruse (Yui NARUSE)</a> suggested me to create a ticket asking for contributions. Is anyone interested in this?</p>
<ul>
<li>This patch changes <code>rsock_getaddrinfo</code> to accept a timeout argument. There are several places where Qnil is passed as a timeout (where I add <code>// TODO</code> in the PoC). We need to consider what timeout we should pass.</li>
<li>This cares only <code>getaddrinfo</code>, but we also need to care <code>getnameinfo</code> (and something else if any). There may be some issues I'm not aware of.</li>
<li>I have not yet tested this PoC seriously. It would be great if we could evaluate it with some real apps.</li>
</ul>
<p>Also, it would be great to hear from someone who knows more about c-ares.</p> Ruby master - Bug #19039 (Open): Closing an IO being select'ed in another thread does not resume ...https://redmine.ruby-lang.org/issues/190392022-10-06T05:30:13Zmame (Yusuke Endoh)mame@ruby-lang.org
<p>Is this intentional?</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">r1</span><span class="p">,</span> <span class="n">w1</span> <span class="o">=</span> <span class="no">IO</span><span class="p">.</span><span class="nf">pipe</span>
<span class="n">r2</span><span class="p">,</span> <span class="n">w2</span> <span class="o">=</span> <span class="no">IO</span><span class="p">.</span><span class="nf">pipe</span>
<span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="nb">select</span><span class="p">([</span><span class="n">r1</span><span class="p">,</span> <span class="n">r2</span><span class="p">])</span>
<span class="nb">p</span> <span class="ss">:ok</span>
<span class="k">end</span>
<span class="nb">sleep</span> <span class="mi">1</span>
<span class="nb">p</span> <span class="n">r1</span><span class="p">.</span><span class="nf">close</span>
<span class="c1"># expected: closing r1 resumes select([r1, r2]) in the thread</span>
<span class="c1"># actual: select([r1, r2]) continues to wait</span>
<span class="nb">sleep</span> <span class="mi">1</span>
<span class="n">w2</span> <span class="o"><<</span> <span class="s2">"foo"</span>
<span class="c1"># Making r2 readable resumes select([r1, r2])</span>
<span class="c1"># And it raises an exception: closed stream (IOError)</span>
<span class="nb">sleep</span> <span class="mi">1</span>
</code></pre>
<p>Incidentally, IO#read is resumed by closing the IO.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">r1</span><span class="p">,</span> <span class="n">w1</span> <span class="o">=</span> <span class="no">IO</span><span class="p">.</span><span class="nf">pipe</span>
<span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">r1</span><span class="p">.</span><span class="nf">read</span>
<span class="nb">p</span> <span class="ss">:ok</span>
<span class="k">end</span>
<span class="nb">sleep</span> <span class="mi">1</span>
<span class="nb">p</span> <span class="n">r1</span><span class="p">.</span><span class="nf">close</span>
<span class="c1"># Closing r1 resumes r1.read in the thread</span>
<span class="c1"># And it raises: stream closed in another thread (IOError)</span>
<span class="nb">sleep</span> <span class="mi">1</span>
</code></pre> Ruby master - Bug #18338 (Open): Encoding.default_external = Encoding::UTF_16BE may add a wrongly...https://redmine.ruby-lang.org/issues/183382021-11-15T07:26:56Zmame (Yusuke Endoh)mame@ruby-lang.org
<pre><code># coding: US-ASCII
Encoding.default_external = Encoding::UTF_16BE
"abc".encode(Encoding.default_external)
p $LOADED_FEATURES.last.encoding #=> #<Encoding:UTF-16BE>
p $LOADED_FEATURES.last
#=> "\u2F68\u6F6D\u652F\u6D61\u6D65\u2F77\u6F72\u6B2F\u7275\u6279\u2F6C\u6F63\u616C\u2F6C\u6962\u2F72\u7562\u792F\u332E\u312E\u302F\u7838\u365F\u3634\u2D6C\u696E\u7578\u2F65\u6E63\u2F74\u7261\u6E73\u2F75\u7466\u5F31\u365F\u3332\u2E73\x6F"
</code></pre>
<p>This weird string seems <code>"/home/mame/work/ruby/local/lib/ruby/3.1.0/x86_64-linux/enc/trans/utf_16_32.s\u0000o".force_encoding("UTF-16BE")</code>.</p>
<p>Note that the code may raise a "code converter not found" error depending on the length of install path (or build path?). Maybe it works if it is even due to UTF-16.</p>
<pre><code># works
mame$ /Users/mame/ruby2/exe/ruby --disable-gems test.rb
#<Encoding:UTF-16BE>
"\u2F55\u7365\u7273\u2F6D\u616D\u652F\u7275\u6279\u322F\u2E65\u7874\u2F78\u3836\u5F36\u342D\u6461\u7277\u696E\u3139\u2F65\u6E63\u2F74\u7261\u6E73\u2F73\u696E\u676C\u655F\u6279\u7465\u2E62\u756E\u646C\x65"
</code></pre>
<pre><code># raises an exception
mame$ /Users/mame/ruby22/exe/ruby --disable-gems test.rb
0ec: 0x0
test.rb:4:in `encode': code converter not found (US-ASCII to UTF-16BE) (Encoding::ConverterNotFoundError)
from test.rb:4:in `<main>'
test.rb:4:in `encode': No such file or directory @ rb_check_realpath_internal - ⽕獥牳⽭慭支牵批㈲⼮數琯砸㙟㘴ⵤ慲睩渱㤯敮振瑲慮猯獩湧汥形祴攮扵湤汥 (Errno::ENOENT)
from test.rb:4:in `<main>'
</code></pre> Ruby master - Feature #17994 (Open): Clarify `IO.read` behavior and add `File.read` methodhttps://redmine.ruby-lang.org/issues/179942021-06-17T03:01:48Zmame (Yusuke Endoh)mame@ruby-lang.org
<p><code>IO.read</code> creates a subprocess when a given file name starts with a <code>|</code> character.</p>
<pre><code>irb(main):001:0> IO.read("| ls /etc/passwd")
=> "/etc/passwd\n"
</code></pre>
<p>To disable this feature, <code>File.read</code> can be used.</p>
<pre><code>irb(main):002:0> File.read("| ls /etc/passwd")
(irb):2:in `read': No such file or directory @ rb_sysopen - | ls /etc/passwd (Errno::ENOENT)
</code></pre>
<p>So, as far as I know, <code>File.read</code> is more prefereable to <code>IO.read</code> if a user want to just read a file.</p>
<p>However, in terms of the implementation, there is no definition of <code>File.read</code>. <code>File.read</code> invokes <code>IO.read</code> because <code>IO</code> is a superclass of <code>File</code>, and <code>IO.read</code> creates a subprocess only when its receiver is exactly the <code>IO</code> class.</p>
<p>I think there are two problems in the current situation:</p>
<ol>
<li>The rdoc of <code>IO.read</code> does not explain the behavior to disable a subprocess invocation.</li>
<li>The rdoc does not have an entry for <code>File.read</code>.</li>
</ol>
<p>I've created a PR to address the two issues by clarifying <code>IO.read</code> behavior and defining <code>File.read</code> as an alias to <code>IO.read</code>.</p>
<p><a href="https://github.com/ruby/ruby/pull/4579" class="external">https://github.com/ruby/ruby/pull/4579</a></p> Ruby master - Feature #17856 (Open): ary.member? is slower than ary.include?https://redmine.ruby-lang.org/issues/178562021-05-11T10:12:14Zmame (Yusuke Endoh)mame@ruby-lang.org
<p><code>Array#include?</code> is defined as a faster version of <code>Enumerable#include?</code>, but there is no <code>Array#member?</code> defined.</p>
<pre><code>$ time ruby -e 'a = (0..100000).to_a; 1000.times { a.member?(100000) }'
real 0m1.722s
user 0m1.721s
sys 0m0.000s
$ time ruby -e 'a = (0..100000).to_a; 1000.times { a.include?(100000) }'
real 0m0.524s
user 0m0.523s
sys 0m0.000s
</code></pre>
<p>I guess this is not intentional. I'll fix this issue unless there is any objection.</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/array.c b/array.c
index 881270b915..92ea9d8059 100644
</span><span class="gd">--- a/array.c
</span><span class="gi">+++ b/array.c
</span><span class="p">@@ -8402,6 +8402,7 @@</span> Init_Array(void)
rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
<span class="gi">+ rb_define_method(rb_cArray, "member?", rb_ary_includes, 1);
</span> rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
<span class="err">
</span> rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
</code></pre> Ruby master - Bug #14090 (Assigned): `TestGc#test_interrupt_in_finalizer` fails very rarelyhttps://redmine.ruby-lang.org/issues/140902017-11-07T07:35:25Zmame (Yusuke Endoh)mame@ruby-lang.org
<p><code>TestGc#test_interrupt_in_finalizer</code> fails very rarely, only once every handred or thousand runs.</p>
<pre><code># Running tests:
[1/1] TestGc#test_interrupt_in_finalizer = 10.13 s
1) Error:
TestGc#test_interrupt_in_finalizer:
Timeout::Error: execution of assert_in_out_err expired
pid 24697 killed by SIGABRT (signal 6) (core dumped)
|
| [BUG] Segmentation fault at 0x000003e800006075
| ruby 2.5.0dev (2017-11-07) [x86_64-linux]
|
| -- Control frame information -----------------------------------------------
|
|
| -- Machine register context ------------------------------------------------
| RIP: 0x00007f80612bb072 RBP: 0x000055c3587e1efc RSP: 0x00007ffc4f8100b0
| RAX: 0xfffffffffffffffc RBX: 0x000055c3587e1ee4 RCX: 0x00007f80612bb072
| RDX: 0x0000000000000000 RDI: 0x000055c3587e1efc RSI: 0x0000000000000080
| R8: 0x00000000000000ca R9: 0x0000000000000000 R10: 0x0000000000000000
| R11: 0x0000000000000246 R12: 0x000055c3587e1ed0 R13: 0x00007ffc4f810110
| R14: 0x000055c3587e1f38 R15: 0x0000000000000003 EFL: 0x0000000000000246
|
| -- C level backtrace information -------------------------------------------
| /home/mame/work/ruby.tmp/ruby(rb_vm_bugreport+0x7d3) [0x55c357e7a333] vm_dump.c:703
| /home/mame/work/ruby.tmp/ruby(rb_bug_context+0xd1) [0x55c357e6de11] error.c:554
| /home/mame/work/ruby.tmp/ruby(sigsegv+0x42) [0x55c357d5e602] signal.c:928
| /lib/x86_64-linux-gnu/libpthread.so.0 [0x7f80612c0150]
| /lib/x86_64-linux-gnu/libpthread.so.0(pthread_cond_wait+0x152) [0x7f80612bb072]
| /home/mame/work/ruby.tmp/ruby(native_sleep.constprop.79+0x1de) [0x55c357d967fe] thread_pthread.c:340
| /home/mame/work/ruby.tmp/ruby(rb_thread_terminate_all+0x1e0) [0x55c357d9aba0] thread.c:507
| /home/mame/work/ruby.tmp/ruby(ruby_cleanup+0x17e) [0x55c357c6078e] eval.c:188
| /home/mame/work/ruby.tmp/ruby(ruby_run_node+0x36) [0x55c357c60aa6] eval.c:302
| /home/mame/work/ruby.tmp/ruby(main+0x5f) [0x55c357c5ca1f] encoding.c:164
|
| -- Other runtime information -----------------------------------------------
|
| * Loaded script: -e
|
| * Loaded features:
|
| 0 enumerator.so
| 1 thread.rb
| 2 rational.so
| 3 complex.so
| 4 /home/mame/work/ruby.tmp/.ext/x86_64-linux/enc/encdb.so
| 5 /home/mame/work/ruby.tmp/.ext/x86_64-linux/enc/trans/transdb.so
| 6 /home/mame/work/ruby.tmp/rbconfig.rb
| 7 /home/mame/work/ruby.tmp/lib/rubygems/compatibility.rb
| 8 /home/mame/work/ruby.tmp/lib/rubygems/defaults.rb
| 9 /home/mame/work/ruby.tmp/lib/rubygems/deprecate.rb
| 10 /home/mame/work/ruby.tmp/lib/rubygems/errors.rb
| 11 /home/mame/work/ruby.tmp/lib/rubygems/version.rb
| 12 /home/mame/work/ruby.tmp/lib/rubygems/requirement.rb
| 13 /home/mame/work/ruby.tmp/lib/rubygems/platform.rb
| 14 /home/mame/work/ruby.tmp/lib/rubygems/basic_specification.rb
| 15 /home/mame/work/ruby.tmp/lib/rubygems/stub_specification.rb
| 16 /home/mame/work/ruby.tmp/lib/rubygems/util/list.rb
| 17 /home/mame/work/ruby.tmp/.ext/x86_64-linux/stringio.so
| 18 /home/mame/work/ruby.tmp/lib/rubygems/specification.rb
| 19 /home/mame/work/ruby.tmp/lib/rubygems/exceptions.rb
| 20 /home/mame/work/ruby.tmp/lib/rubygems/core_ext/kernel_gem.rb
| 21 /home/mame/work/ruby.tmp/lib/monitor.rb
| 22 /home/mame/work/ruby.tmp/lib/rubygems/core_ext/kernel_require.rb
| 23 /home/mame/work/ruby.tmp/lib/rubygems.rb
| 24 /home/mame/work/ruby.tmp/lib/rubygems/dependency.rb
| 25 /home/mame/work/ruby.tmp/lib/rubygems/path_support.rb
|
| * Process memory map:
|
| 55c357c3a000-55c357f55000 r-xp 00000000 fd:01 21892603 /home/mame/work/ruby.tmp/ruby
| 55c358155000-55c35815a000 r--p 0031b000 fd:01 21892603 /home/mame/work/ruby.tmp/ruby
| 55c35815a000-55c35815b000 rw-p 00320000 fd:01 21892603 /home/mame/work/ruby.tmp/ruby
| 55c35815b000-55c35816c000 rw-p 00000000 00:00 0
| 55c3587e1000-55c358b0d000 rw-p 00000000 00:00 0 [heap]
| 7f8058000000-7f8058021000 rw-p 00000000 00:00 0
| 7f8058021000-7f805c000000 ---p 00000000 00:00 0
| 7f805e93f000-7f805eb1e000 r--s 00000000 fd:01 15604574 /lib/x86_64-linux-gnu/libc-2.26.so
| 7f805eb1e000-7f805fb92000 r--s 00000000 fd:01 21892603 /home/mame/work/ruby.tmp/ruby
| 7f805fb92000-7f805fba8000 r-xp 00000000 fd:01 15597591 /lib/x86_64-linux-gnu/libgcc_s.so.1
| 7f805fba8000-7f805fda7000 ---p 00016000 fd:01 15597591 /lib/x86_64-linux-gnu/libgcc_s.so.1
| 7f805fda7000-7f805fda8000 r--p 00015000 fd:01 15597591 /lib/x86_64-linux-gnu/libgcc_s.so.1
| 7f805fda8000-7f805fda9000 rw-p 00016000 fd:01 15597591 /lib/x86_64-linux-gnu/libgcc_s.so.1
| 7f805fda9000-7f805feaa000 rw-p 00000000 00:00 0
| 7f805feaa000-7f805feb3000 r-xp 00000000 fd:01 23333969 /home/mame/work/ruby.tmp/.ext/x86_64-linux/stringio.so
| 7f805feb3000-7f80600b2000 ---p 00009000 fd:01 23333969 /home/mame/work/ruby.tmp/.ext/x86_64-linux/stringio.so
| 7f80600b2000-7f80600b3000 r--p 00008000 fd:01 23333969 /home/mame/work/ruby.tmp/.ext/x86_64-linux/stringio.so
| 7f80600b3000-7f80600b4000 rw-p 00009000 fd:01 23333969 /home/mame/work/ruby.tmp/.ext/x86_64-linux/stringio.so
| 7f80600b4000-7f80600b6000 r-xp 00000000 fd:01 23333689 /home/mame/work/ruby.tmp/.ext/x86_64-linux/enc/trans/transdb.so
| 7f80600b6000-7f80602b6000 ---p 00002000 fd:01 23333689 /home/mame/work/ruby.tmp/.ext/x86_64-linux/enc/trans/transdb.so
| 7f80602b6000-7f80602b7000 r--p 00002000 fd:01 23333689 /home/mame/work/ruby.tmp/.ext/x86_64-linux/enc/trans/transdb.so
| 7f80602b7000-7f80602b8000 rw-p 00003000 fd:01 23333689 /home/mame/work/ruby.tmp/.ext/x86_64-linux/enc/trans/transdb.so
| 7f80602b8000-7f80602ba000 r-xp 00000000 fd:01 23333649 /home/mame/work/ruby.tmp/.ext/x86_64-linux/enc/encdb.so
| 7f80602ba000-7f80604b9000 ---p 00002000 fd:01 23333649 /home/mame/work/ruby.tmp/.ext/x86_64-linux/enc/encdb.so
| 7f80604b9000-7f80604ba000 r--p 00001000 fd:01 23333649 /home/mame/work/ruby.tmp/.ext/x86_64-linux/enc/encdb.so
| 7f80604ba000-7f80604bb000 rw-p 00002000 fd:01 23333649 /home/mame/work/ruby.tmp/.ext/x86_64-linux/enc/encdb.so
| 7f80604bb000-7f8060691000 r-xp 00000000 fd:01 15604574 /lib/x86_64-linux-gnu/libc-2.26.so
| 7f8060691000-7f8060891000 ---p 001d6000 fd:01 15604574 /lib/x86_64-linux-gnu/libc-2.26.so
| 7f8060891000-7f8060895000 r--p 001d6000 fd:01 15604574 /lib/x86_64-linux-gnu/libc-2.26.so
| 7f8060895000-7f8060897000 rw-p 001da000 fd:01 15604574 /lib/x86_64-linux-gnu/libc-2.26.so
| 7f8060897000-7f806089b000 rw-p 00000000 00:00 0
| 7f806089b000-7f80609f0000 r-xp 00000000 fd:01 15604578 /lib/x86_64-linux-gnu/libm-2.26.so
| 7f80609f0000-7f8060bef000 ---p 00155000 fd:01 15604578 /lib/x86_64-linux-gnu/libm-2.26.so
| 7f8060bef000-7f8060bf0000 r--p 00154000 fd:01 15604578 /lib/x86_64-linux-gnu/libm-2.26.so
| 7f8060bf0000-7f8060bf1000 rw-p 00155000 fd:01 15604578 /lib/x86_64-linux-gnu/libm-2.26.so
| 7f8060bf1000-7f8060bfa000 r-xp 00000000 fd:01 15604576 /lib/x86_64-linux-gnu/libcrypt-2.26.so
| 7f8060bfa000-7f8060df9000 ---p 00009000 fd:01 15604576 /lib/x86_64-linux-gnu/libcrypt-2.26.so
| 7f8060df9000-7f8060dfa000 r--p 00008000 fd:01 15604576 /lib/x86_64-linux-gnu/libcrypt-2.26.so
| 7f8060dfa000-7f8060dfb000 rw-p 00009000 fd:01 15604576 /lib/x86_64-linux-gnu/libcrypt-2.26.so
| 7f8060dfb000-7f8060e29000 rw-p 00000000 00:00 0
| 7f8060e29000-7f8060e2c000 r-xp 00000000 fd:01 15604577 /lib/x86_64-linux-gnu/libdl-2.26.so
| 7f8060e2c000-7f806102b000 ---p 00003000 fd:01 15604577 /lib/x86_64-linux-gnu/libdl-2.26.so
| 7f806102b000-7f806102c000 r--p 00002000 fd:01 15604577 /lib/x86_64-linux-gnu/libdl-2.26.so
| 7f806102c000-7f806102d000 rw-p 00003000 fd:01 15604577 /lib/x86_64-linux-gnu/libdl-2.26.so
| 7f806102d000-7f80610ab000 r-xp 00000000 fd:01 12068737 /usr/lib/x86_64-linux-gnu/libgmp.so.10.3.2
| 7f80610ab000-7f80612ab000 ---p 0007e000 fd:01 12068737 /usr/lib/x86_64-linux-gnu/libgmp.so.10.3.2
| 7f80612ab000-7f80612ac000 r--p 0007e000 fd:01 12068737 /usr/lib/x86_64-linux-gnu/libgmp.so.10.3.2
| 7f80612ac000-7f80612ad000 rw-p 0007f000 fd:01 12068737 /usr/lib/x86_64-linux-gnu/libgmp.so.10.3.2
| 7f80612ad000-7f80612c7000 r-xp 00000000 fd:01 15604589 /lib/x86_64-linux-gnu/libpthread-2.26.so
| 7f80612c7000-7f80614c6000 ---p 0001a000 fd:01 15604589 /lib/x86_64-linux-gnu/libpthread-2.26.so
| 7f80614c6000-7f80614c7000 r--p 00019000 fd:01 15604589 /lib/x86_64-linux-gnu/libpthread-2.26.so
| 7f80614c7000-7f80614c8000 rw-p 0001a000 fd:01 15604589 /lib/x86_64-linux-gnu/libpthread-2.26.so
| 7f80614c8000-7f80614cc000 rw-p 00000000 00:00 0
| 7f80614cc000-7f80614f3000 r-xp 00000000 fd:01 15602223 /lib/x86_64-linux-gnu/ld-2.26.so
| 7f8061592000-7f80615b6000 r--s 00000000 fd:01 15604589 /lib/x86_64-linux-gnu/libpthread-2.26.so
| 7f80615b6000-7f80616bc000 rw-p 00000000 00:00 0
| 7f80616cb000-7f80616cc000 ---p 00000000 00:00 0
| 7f80616cc000-7f80616ec000 rw-p 00000000 00:00 0
| 7f80616ec000-7f80616ed000 ---p 00000000 00:00 0
| 7f80616ed000-7f80616f3000 rw-p 00000000 00:00 0
| 7f80616f3000-7f80616f4000 r--p 00027000 fd:01 15602223 /lib/x86_64-linux-gnu/ld-2.26.so
| 7f80616f4000-7f80616f5000 rw-p 00028000 fd:01 15602223 /lib/x86_64-linux-gnu/ld-2.26.so
| 7f80616f5000-7f80616f6000 rw-p 00000000 00:00 0
| 7ffc4f013000-7ffc4f812000 rw-p 00000000 00:00 0 [stack]
| 7ffc4f904000-7ffc4f907000 r--p 00000000 00:00 0 [vvar]
| 7ffc4f907000-7ffc4f909000 r-xp 00000000 00:00 0 [vdso]
| ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
|
|
| [NOTE]
| You may have encountered a bug in the Ruby interpreter or extension libraries.
| Bug reports are welcome.
| For details: http://www.ruby-lang.org/bugreport.html
|
/home/mame/work/ruby.tmp/test/ruby/test_gc.rb:354:in `test_interrupt_in_finalizer'
Finished tests in 10.127763s, 0.0987 tests/s, 0.2962 assertions/s.
1 tests, 3 assertions, 0 failures, 1 errors, 0 skips
</code></pre>
<a name="How-to-reproduce"></a>
<h2 >How to reproduce<a href="#How-to-reproduce" class="wiki-anchor">¶</a></h2>
<ol>
<li>Apply this patch. This removes a mitigation of this issue.</li>
</ol>
<pre><code>diff --git a/thread.c b/thread.c
index bfa903c6a4..dfaf75d1ce 100644
--- a/thread.c
+++ b/thread.c
@@ -507,7 +507,7 @@ rb_thread_terminate_all(void)
* me when the last sub-thread exit.
*/
sleeping = 1;
- native_sleep(th, &tv);
+ native_sleep(th, 0);
RUBY_VM_CHECK_INTS_BLOCKING(ec);
sleeping = 0;
}
</code></pre>
<ol start="2">
<li>Run <code>make test-all</code> many times. The following command would be useful.</li>
</ol>
<pre><code>make && while make test-all TESTOPTS="test/ruby/test_gc.rb -n test_interrupt_in_finalizer"; do date; done
</code></pre>
<p>FYI: With execution counter</p>
<pre><code>make && i=0 && while make test-all TESTOPTS="test/ruby/test_gc.rb -n test_interrupt_in_finalizer"; do echo; date; echo "trial:$i"; i=`expr $i + 1`; done
</code></pre>
<a name="Details"></a>
<h2 >Details<a href="#Details" class="wiki-anchor">¶</a></h2>
<p><code>TestGc#test_interrupt_in_finalizer</code> checks if SIGINT can interrupt the GC finalizers. This test itself runs on a child process, and the process should end with SIGINT. If the process does not end in ten seconds, the parent sends SIGSEGV to the child, terminates the test, and reports it as a failure. ("C level backtrace information" has "sigsegv", but don't worry, this SEGV would be the one the parent sent. I guess this bug is not so significant, parhaps.)</p>
<p>When a main thread of Ruby process ends, it terminates all child threads and waits for them. However, for unknown reason (maybe depending upon the timing of SIGINT?), it sometimes fails synchronization: all child threads end, and the main thread meaninglessly waits forever.</p>
<p>Based on Ko1's proposal, I committed a tiny change to mitigate this issue at r60694: instead of waiting forever, the main thread wakes up every one second to monitor all child threads. This is not an essential solution for this issue, but just hides. To debug this issue, we need remove the mitigation by the patch described above.</p> Ruby master - Feature #12543 (Assigned): explicit tail call syntax: foo() then returnhttps://redmine.ruby-lang.org/issues/125432016-07-02T17:24:19Zmame (Yusuke Endoh)mame@ruby-lang.org
<p>How about introducing a new syntax for tail call?</p>
<pre><code>def foo()
foo()
end
foo() #=> stack level too deep
</code></pre>
<pre><code>def bar()
bar() then return
end
bar() #=> infinite loop
</code></pre>
<ul>
<li>no new keyword (cf. <code>goto foo()</code>)</li>
<li>no conflict with any existing syntax</li>
<li>an experimental patch is available (attached)</li>
<li>no shift/reduce nor reduce/reduce conflict in parse.y</li>
</ul>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@ruby-lang.org" class="email">mame@ruby-lang.org</a></p> Ruby master - Feature #12497 (Assigned): GMP version of divmod may be slowerhttps://redmine.ruby-lang.org/issues/124972016-06-16T17:04:12Zmame (Yusuke Endoh)mame@ruby-lang.org
<p><a href="https://benchmarksgame.alioth.debian.org/u64q/program.php?test=pidigits&lang=yarv&id=3" class="external">The benchmark program <code>pidigits.rb</code></a> runs faster if USE_GMP is disabled for divmod.</p>
<pre><code>$ time ./miniruby.orig pidigits.rb 10000 > /dev/null
real 0m5.932s
user 0m5.740s
sys 0m0.188s
</code></pre>
<pre><code>$ time ./miniruby.patched pidigits.rb 10000 > /dev/null
real 0m3.212s
user 0m3.056s
sys 0m0.152s
</code></pre>
<pre><code>diff --git a/bignum.c b/bignum.c
index 767659d..33a172e 100644
--- a/bignum.c
+++ b/bignum.c
@@ -2813,12 +2813,6 @@ rb_big_divrem_gmp(VALUE x, VALUE y)
static void
bary_divmod_branch(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
{
-#ifdef USE_GMP
- if (GMP_DIV_DIGITS < xn) {
- bary_divmod_gmp(qds, qn, rds, rn, xds, xn, yds, yn);
- return;
- }
-#endif
bary_divmod_normal(qds, qn, rds, rn, xds, xn, yds, yn);
}
</code></pre>
<p>We can possibly tune performance.</p> Ruby master - Feature #11177 (Open): DATAでEOF文字以降が読めないhttps://redmine.ruby-lang.org/issues/111772015-05-24T05:53:55Zmame (Yusuke Endoh)mame@ruby-lang.org
<p>遠藤です。</p>
<p>Windows で <code>__END__</code> 以降に EOF 文字 (<code>\x1A</code>) があったとき、それより先が読めないのは仕様でしょうか。</p>
<p>gen.rb:</p>
<pre><code>puts "p DATA.read"
puts "__END__"
puts "foo\x1Abar"
</code></pre>
<p>以下のように実行すると再現します。</p>
<pre><code>> ruby gen.rb > t.rb
> ruby t.rb
"foo"
</code></pre>
<p><code>DATA.binmode.read</code> などとしてみても同じです。</p>
<p>もちろん、Linux では先まで読めます。Windows でも、ソースコードをパイプで流し込んだ場合はなぜか読めます。</p>
<pre><code>> ruby < t.rb
"foo\x1Abar\n"
</code></pre>
<p>さらに、EOF 以降に文字がいっぱいあった場合、EOF 以降の一部の文字が抜け落ちるような挙動になるようです。</p>
<p>gen2.rb:</p>
<pre><code>puts "p DATA.read"
puts "__END__"
puts "foo\x1A" + "X" * 8192 + "Z"
> ruby gen2.rb > t.rb
> ruby t.rb
"fooXXXXXXXXXXXXXXXXXXXXXXXXXXXZ\r\n"
</code></pre>
<p>バッファリングのバグっぽい挙動ですが、バグでしょうか。</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@ruby-lang.org" class="email">mame@ruby-lang.org</a></p> Ruby master - Feature #4831 (Assigned): Integer#prime_factorshttps://redmine.ruby-lang.org/issues/48312011-06-06T00:33:11Zmame (Yusuke Endoh)mame@ruby-lang.org
<p>Hello,</p>
<p>lib/prime provides Integer#prime_division, but I always forget the name.<br>
I think that #prime_factors is more suitable. I'd like to hear opinions<br>
of English natives. What do you think?</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p>