Ruby Issue Tracking System: Issueshttps://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112024-03-19T09:10:29ZRuby Issue Tracking System
Redmine Ruby master - Feature #20347 (Assigned): Separate docs task from allhttps://redmine.ruby-lang.org/issues/203472024-03-19T09:10:29Zhsbt (Hiroshi SHIBATA)hsbt@ruby-lang.org
<p>I would like to migrate RDoc as bundled gems at Ruby 3.5.</p>
<p>We need to handle <code>install-doc</code> and related task with that. I removed <code>docs</code> task from <code>all</code> and re-order <code>docs</code> task at <code>install-all</code>.</p>
<p><a href="https://github.com/ruby/ruby/pull/10282" class="external">https://github.com/ruby/ruby/pull/10282</a></p>
<p>It works with RDoc as bundled gems. We can keep current behavior with this migration.</p>
<p>I hope to merge changes for <code>all</code> task and re-order <code>install-all</code> task at Ruby 3.4.</p>
<p><a href="https://github.com/ruby/ruby/pull/10282/commits/b160083175aed062c320b8d76eafe1c8706309d4" class="external">https://github.com/ruby/ruby/pull/10282/commits/b160083175aed062c320b8d76eafe1c8706309d4</a></p>
<p>After that, the default <code>make</code> task will not generate rdoc. We need to add <code>make all docs</code> for that.</p> Ruby master - Feature #20309 (Assigned): Bundled gems for Ruby 3.5https://redmine.ruby-lang.org/issues/203092024-02-27T22:16:20Zhsbt (Hiroshi SHIBATA)hsbt@ruby-lang.org
<p>I propose migrate the following default gems to bundled gems at Ruby 3.5. So, It means users will get warnings if users try to load them.</p>
<p>(Update with 2024/03/14)</p>
<ul>
<li>ostruct
<ul>
<li>I make ostruct as optional on json at <a href="https://github.com/flori/json/pull/565" class="external">https://github.com/flori/json/pull/565</a>
</li>
</ul>
</li>
<li>logger
<ul>
<li>activesupport needs to add logger to its dependency same as bigdecimal, drb or etc.</li>
</ul>
</li>
<li>fiddle</li>
<li>pstore</li>
<li>win32ole</li>
</ul>
<p>I have a plan to migrate the following default gems too. But I need to more feedback from other committers about them.</p>
<ul>
<li>irb
<ul>
<li>We need to consider how works <code>binding.irb</code> after Ruby 3.5.</li>
<li>I consider to use <code>irb</code> without Gemfile.</li>
</ul>
</li>
<li>reline</li>
<li>readline (wrapper file for readline-ext and reline)</li>
<li>io-console
<ul>
<li>rubygems uses that. Should we make optional that?</li>
</ul>
</li>
<li>open-uri</li>
<li>yaml (wrapper file for psych)
<ul>
<li>syck is retired today. I'm not sure what people uses <code>psych</code> directly, not <code>yaml</code>.</li>
</ul>
</li>
<li>rdoc
<ul>
<li>We need to change build task like download rdoc gem before document generation.
<ul>
<li>extract <code>make doc</code> from <code>make all</code> and invoke <code>make doc</code> before <code>make install</code>.</li>
</ul>
</li>
<li>or We make document generation is optional from Ruby 3.5
<ul>
<li>We explicitly separate <code>make install</code> and <code>make install-doc</code>
</li>
</ul>
</li>
</ul>
</li>
<li>un
<ul>
<li>
<code>ruby -run</code> is one of cool feature of Ruby. Should we avoid uninstalling <code>un</code> gem?</li>
<li>mkmf uses <code>ruby -run</code> for that. I need to investigate that.</li>
</ul>
</li>
<li>singleton
<ul>
<li>This is famous design pattern. Should we enforce users add them to their Gemfile?</li>
</ul>
</li>
<li>forwadable
<ul>
<li>
<code>reline</code> needs to add forwardable their <code>runtime_dependency</code> after migration.</li>
</ul>
</li>
<li>weakref
<ul>
<li>I'm not sure how impact after migrating bundled gems.</li>
</ul>
</li>
<li>fcntl
<ul>
<li>Should we integrate these constants into ruby core?</li>
</ul>
</li>
</ul>
<p>I would like to migrate <code>ipaddr</code> and <code>uri</code> too. But these are used by webrick that is mock server for our test suite. We need to rewrite <code>webrick</code> with <code>TCPSocker</code> or extract <code>ipaddr</code> and <code>uri</code> dependency from <code>webrick</code></p>
<p>Other default gems depend on our build process or other libraries deeply. I will update this proposal if I could extract them from default gems.</p> Ruby master - Bug #20285 (Assigned): Stale inline method caches when refinement modules are reopenedhttps://redmine.ruby-lang.org/issues/202852024-02-21T02:44:55Zjhawthorn (John Hawthorn)
<p>This is essentially the same issue as <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: refinement (Closed)" href="https://redmine.ruby-lang.org/issues/11672">#11672</a>, but for inline method caches rather than class caches.</p>
<p>In Ruby 3.3 we started using inline caches for refinements. However, we weren't clearing inline caches when defined on a reopened refinement module.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">C</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">R</span>
<span class="n">refine</span> <span class="no">C</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">m</span>
<span class="ss">:foo</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">using</span> <span class="no">R</span>
<span class="k">def</span> <span class="nf">m</span>
<span class="no">C</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">m</span>
<span class="k">end</span>
<span class="k">raise</span> <span class="k">unless</span> <span class="ss">:foo</span> <span class="o">==</span> <span class="n">m</span><span class="p">()</span>
<span class="k">module</span> <span class="nn">R</span>
<span class="n">refine</span> <span class="no">C</span> <span class="k">do</span>
<span class="k">alias</span> <span class="n">m</span> <span class="n">m</span>
<span class="k">def</span> <span class="nf">m</span>
<span class="ss">:bar</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">v</span> <span class="o">=</span> <span class="n">m</span><span class="p">()</span>
<span class="k">raise</span> <span class="s2">"expected :bar, got </span><span class="si">#{</span><span class="n">v</span><span class="p">.</span><span class="nf">inspect</span><span class="si">}</span><span class="s2">"</span> <span class="k">unless</span> <span class="ss">:bar</span> <span class="o">==</span> <span class="n">v</span>
</code></pre>
<p>This will raise in Ruby 3.3 as the inline cache finds a stale refinement, but passes in previous versions.</p> Ruby master - Bug #20237 (Assigned): Unable to unshare(CLONE_NEWUSER) in Linux because of timer t...https://redmine.ruby-lang.org/issues/202372024-02-05T04:59:20Zhanazuki (Kasumi Hanazuki)
<a name="Backgrounds"></a>
<h2 >Backgrounds<a href="#Backgrounds" class="wiki-anchor">¶</a></h2>
<p><a href="https://man7.org/linux/man-pages/man2/unshare.2.html" class="external">unshare(2)</a> is a syscall in Linux to move the calling process into a fresh execution context. With <code>unshare(CLONE_NEWUSER)</code> you can move a process into a new <a href="https://man7.org/linux/man-pages/man7/user_namespaces.7.html" class="external">user_namespace(7)</a>, where the process gains the full capability on the resources within the namespace. This is fundamental for Linux containers to achieve privilege separation. <code>unshare(CLONE_NEWUSER)</code> requires the calling process to be single-threaded (or no background threads are running). So, it is often invoked after <code>fork(2)</code> as forking propagates only the calling thread to the child process.</p>
<a name="Problem"></a>
<h2 >Problem<a href="#Problem" class="wiki-anchor">¶</a></h2>
<p>It becomes a problem that Ruby 3.3 on Linux uses timer threads even for a single-<code>Thread</code>ed application. Because <code>Kernel#fork</code> spawns a thread in the child process before the control returns to the user code, there is no chance to call <code>unshare(CLONE_NEWUSER)</code> in Ruby.</p>
<p>The following snippet is a reproducer of this problem. This program first forks and then shows the user namespace to which the process belongs before and after calling unshare(2). It also shows the threads of the child process after forking.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">p</span><span class="p">(</span><span class="no">RUBY_DESCRIPTION</span><span class="p">:)</span>
<span class="nb">require</span> <span class="s1">'fiddle/import'</span>
<span class="k">module</span> <span class="nn">C</span>
<span class="kp">extend</span> <span class="no">Fiddle</span><span class="o">::</span><span class="no">Importer</span>
<span class="n">dlload</span> <span class="s1">'libc.so.6'</span>
<span class="n">extern</span> <span class="s1">'int unshare(int flags)'</span>
<span class="no">CLONE_NEWUSER</span> <span class="o">=</span> <span class="mh">0x10000000</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">raise_system_call_error</span>
<span class="k">raise</span> <span class="no">SystemCallError</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">Fiddle</span><span class="p">.</span><span class="nf">last_error</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">pid</span> <span class="o">=</span> <span class="nb">fork</span> <span class="k">do</span>
<span class="nb">system</span><span class="p">(</span><span class="s2">"ps -O tid -T -p #$$"</span><span class="p">)</span>
<span class="nb">system</span><span class="p">(</span><span class="s2">"ls -l /proc/self/ns/user"</span><span class="p">)</span>
<span class="k">if</span> <span class="no">C</span><span class="p">.</span><span class="nf">unshare</span><span class="p">(</span><span class="no">C</span><span class="o">::</span><span class="no">CLONE_NEWUSER</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span>
<span class="no">C</span><span class="p">.</span><span class="nf">raise_system_call_error</span> <span class="c1"># => EINVAL with Ruby 3.3</span>
<span class="k">end</span>
<span class="nb">system</span><span class="p">(</span><span class="s2">"ls -l /proc/self/ns/user"</span><span class="p">)</span>
<span class="k">end</span>
<span class="nb">p</span> <span class="no">Process</span><span class="p">.</span><span class="nf">wait2</span><span class="p">(</span><span class="n">pid</span><span class="p">)</span>
</code></pre>
<p>The program successfully changes the user namespace with Ruby 3.2, but it raises EINVAL with Ruby 3.3. You can see Ruby 3.3 has two threads running after forking.</p>
<pre><code>% rbenv shell 3.2 && ruby ./test.rb
{:RUBY_DESCRIPTION=>"ruby 3.2.3 (2024-01-18 revision 52bb2ac0a6) [x86_64-linux]"}
PID TID S TTY TIME COMMAND
1585787 1585787 S pts/12 00:00:00 ruby ./test.rb
lrwxrwxrwx 1 kasumi kasumi 0 Feb 5 02:25 /proc/self/ns/user -> 'user:[4026531837]'
lrwxrwxrwx 1 nobody nogroup 0 Feb 5 02:25 /proc/self/ns/user -> 'user:[4026532675]'
[1585787, #<Process::Status: pid 1585787 exit 0>]
% rbenv shell 3.3 && ruby ./test.rb
{:RUBY_DESCRIPTION=>"ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux]"}
PID TID S TTY TIME COMMAND
1585849 1585849 S pts/12 00:00:00 ruby ./test.rb
1585849 1585851 S pts/12 00:00:00 ruby ./test.rb
lrwxrwxrwx 1 kasumi kasumi 0 Feb 5 02:25 /proc/self/ns/user -> 'user:[4026531837]'
./test.rb:10:in `raise_system_call_error': Invalid argument (Errno::EINVAL)
from ./test.rb:24:in `block in <main>'
from ./test.rb:19:in `fork'
from ./test.rb:19:in `<main>'
[1585849, #<Process::Status: pid 1585849 exit 1>]
% rbenv shell master && ruby ./test.rb
{:RUBY_DESCRIPTION=>"ruby 3.4.0dev (2024-02-04T16:05:02Z master 8bc6fff322) [x86_64-linux]"}
PID TID S TTY TIME COMMAND
1585965 1585965 S pts/12 00:00:00 ruby ./test.rb
1585965 1585967 S pts/12 00:00:00 ruby ./test.rb
lrwxrwxrwx 1 kasumi kasumi 0 Feb 5 02:25 /proc/self/ns/user -> 'user:[4026531837]'
./test.rb:10:in `raise_system_call_error': Invalid argument (Errno::EINVAL)
from ./test.rb:24:in `block in <main>'
from ./test.rb:19:in `fork'
from ./test.rb:19:in `<main>'
[1585965, #<Process::Status: pid 1585965 exit 1>]
</code></pre>
<a name="Workaround"></a>
<h2 >Workaround<a href="#Workaround" class="wiki-anchor">¶</a></h2>
<p>My workaround is to rebuild ruby with <code>rb_thread_stop_timer_thread</code> and <code>rb_thread_start_timer_thread</code> exported, and use a C-ext that stops the timer thread before calling <code>unshare</code>. This seems not robust because the process cannot know when the terminated thread is reclaimed by the kernel, after which the process is considered single-threaded.</p>
<pre><code class="c syntaxhl" data-language="c"><span class="cp">#define _GNU_SOURCE 1
#include</span> <span class="cpf"><sched.h></span><span class="cp">
#include</span> <span class="cpf"><ruby/ruby.h></span><span class="cp">
</span>
<span class="k">static</span> <span class="n">VALUE</span> <span class="nf">Unshare_s_unshare</span><span class="p">(</span><span class="n">VALUE</span> <span class="n">_self</span><span class="p">,</span> <span class="n">VALUE</span> <span class="n">rflags</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">int</span> <span class="k">const</span> <span class="n">flags</span> <span class="o">=</span> <span class="n">NUM2INT</span><span class="p">(</span><span class="n">rflags</span><span class="p">);</span>
<span class="n">rb_thread_stop_timer_thread</span><span class="p">();</span>
<span class="n">usleep</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span> <span class="c1">// FIXME: It takes some time for the kernel to remove the stopped thread?</span>
<span class="kt">int</span> <span class="k">const</span> <span class="n">ret</span> <span class="o">=</span> <span class="n">unshare</span><span class="p">(</span><span class="n">flags</span><span class="p">);</span>
<span class="n">rb_thread_start_timer_thread</span><span class="p">();</span>
<span class="k">if</span><span class="p">(</span><span class="n">ret</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="n">rb_sys_fail_str</span><span class="p">(</span><span class="n">rb_sprintf</span><span class="p">(</span><span class="s">"unshare(%#x)"</span><span class="p">,</span> <span class="n">flags</span><span class="p">));</span>
<span class="k">return</span> <span class="n">Qnil</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">RUBY_FUNC_EXPORTED</span> <span class="kt">void</span>
<span class="nf">Init_unshare</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
<span class="n">VALUE</span> <span class="n">rb_mUnshare</span> <span class="o">=</span> <span class="n">rb_define_module</span><span class="p">(</span><span class="s">"Unshare"</span><span class="p">);</span>
<span class="n">rb_define_singleton_method</span><span class="p">(</span><span class="n">rb_mUnshare</span><span class="p">,</span> <span class="s">"unshare"</span><span class="p">,</span> <span class="n">Unshare_s_unshare</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">rb_define_const</span><span class="p">(</span><span class="n">rb_mUnshare</span><span class="p">,</span> <span class="s">"CLONE_NEWUSER"</span><span class="p">,</span> <span class="n">INT2FIX</span><span class="p">(</span><span class="n">CLONE_NEWUSER</span><span class="p">));</span>
<span class="p">}</span>
</code></pre>
<a name="Questions"></a>
<h2 >Questions<a href="#Questions" class="wiki-anchor">¶</a></h2>
<ul>
<li>Is this a limitation of Ruby?</li>
<li>Is it safe (or even possible) to stop the timer thread during execution?
<ul>
<li>If so, can we export it as the public API?</li>
<li>But it may not so useful for this problem as explained in the workaround.</li>
</ul>
</li>
<li>Is it guaranteed that no other threads are running after forks?</li>
<li>Are there any better ways to solve this issue?
<ul>
<li>Can we somehow delay the start of the timer thread after forking, or hook into <code>fork</code> to run some code in the child process immediately after it spawns.</li>
<li>Can they be Ruby API instead of C API?</li>
</ul>
</li>
</ul> Ruby master - Bug #20158 (Assigned): Ractor affects Coverage resultshttps://redmine.ruby-lang.org/issues/201582024-01-07T15:12:34Zjanosch-x (Janosch Müller)
<p>I have a large rspec test suite. I found that if I call a Ractor, the Coverage results are strongly affected, i.e. almost all files appear to be uncovered. This happens even if I only ever call a Ractor before the library or rspec are required.</p>
<p>Unfortunately, I was not able to build a simple repro yet.</p>
<p>I assume it is a timing thing and only affects larger suites, or it only happens if there are multiple files, and maybe if the library lazily requires its sub-modules?</p>
<p>However, I guess this should produce the same results when added to the spec_helper.rb of other large suites:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># Ractor.new { nil } # uncomment this to affect coverage results</span>
<span class="nb">require</span> <span class="s1">'coverage'</span>
<span class="no">Coverage</span><span class="p">.</span><span class="nf">start</span>
<span class="c1"># require library, set up rspec etc. </span>
<span class="no">RSpec</span><span class="p">.</span><span class="nf">configuration</span><span class="p">.</span><span class="nf">after</span><span class="p">(</span><span class="ss">:suite</span><span class="p">)</span> <span class="k">do</span>
<span class="c1"># this number is greatly reduced and unstable when calling Ractor above</span>
<span class="nb">p</span> <span class="no">Coverage</span><span class="p">.</span><span class="nf">result</span><span class="p">.</span><span class="nf">values</span><span class="p">.</span><span class="nf">sum</span> <span class="p">{</span> <span class="o">|</span><span class="n">arr</span><span class="o">|</span> <span class="n">arr</span><span class="p">.</span><span class="nf">sum</span><span class="p">(</span><span class="o">&</span><span class="ss">:to_i</span><span class="p">)</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<p>I had this problem in <a href="https://github.com/jaynetics/character_set/" class="external">this library</a>. The problem affects simplecov users as well, as described <a href="https://github.com/simplecov-ruby/simplecov/issues/1058" class="external">here</a>.</p> Ruby master - Bug #20155 (Assigned): Using value of rb_fiber_scheduler_current() crashes Rubyhttps://redmine.ruby-lang.org/issues/201552024-01-05T22:14:24Zpaddor (Patrik Wenger)paddor@gmail.com
<p>While trying to manually block/unblock fibers from an extension using the Fiber Scheduler,<br>
I noticed that using the return value of <code>rb_fiber_scheduler_current()</code> crashes Ruby.</p>
<p>I've created a minimal extension gem called "fiber_blocker". Its test suite shows the behavior. See <a href="https://github.com/paddor/fiber_blocker" class="external">https://github.com/paddor/fiber_blocker</a>, especially the lines containing <code>FIXME</code>.</p>
<p>Passing <code>Fiber.scheduler</code> to the extension functions works. But letting it get the current scheduler itself does not seem to work.</p>
<p>Is <code>rb_fiber_scheduler_current()</code>(within a non-blocking Fiber) not the equivalent to <code>Fiber.scheduler</code>?<br>
Even just printing the its return value with <code>#p</code> will crash Ruby.</p>
<p>Ruby either crashes like this:</p>
<pre><code># Running:
T1 BEGIN
T2 BEGIN
T1 END
..T1 BEGIN
ext: blocking fiber
passed scheduler = #<Scheduler:0x00007fc5f22d39e8 @readable={}, @writable={}, @waiting={}, @closed=false, @lock=#<Thread::Mutex:0x00007fc5f22ec8d0>, @blocking={}, @ready=[], @urgent=[#<IO:fd 5>, #<IO:fd 6>]>
T2 BEGIN
ext: unblocking fiber
T1 END
.E
Finished in 1.007014s, 3.9721 runs/s, 2.9791 assertions/s.
1) Error:
TestFiberBlocker#test_fiber_blocker_current_fiber:
fatal: machine stack overflow in critical region
No backtrace
</code></pre>
<p>Or with a segfault:</p>
<pre><code># Running:
FiberBlocker.test works.
.T1 BEGIN
T2 BEGIN
T1 END
.T1 BEGIN
ext: blocking fiber
/home/user/dev/oss/async_ruby_test/rbnng/fiber_blocker/test/test_fiber_blocker.rb:40: [BUG] Segmentation fault at 0x00000000390d8f98
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux]
-- Control frame information -----------------------------------------------
c:0003 p:---- s:0012 e:000011 CFUNC :block_fiber
c:0002 p:0014 s:0006 e:000005 BLOCK /home/user/dev/oss/async_ruby_test/rbnng/fiber_blocker/test/test_fiber_blocker.rb:40 [FINISH]
c:0001 p:---- s:0003 e:000002 DUMMY [FINISH]
-- Ruby level backtrace information ----------------------------------------
/home/user/dev/oss/async_ruby_test/rbnng/fiber_blocker/test/test_fiber_blocker.rb:40:in `block in test_fiber_blocking_in_ext'
/home/user/dev/oss/async_ruby_test/rbnng/fiber_blocker/test/test_fiber_blocker.rb:40:in `block_fiber'
-- Threading information ---------------------------------------------------
Total ractor count: 1
Ruby thread count for this ractor: 4
-- Machine register context ------------------------------------------------
RIP: 0x00007f1554f17ad8 RBP: 0x00000000390d8f90 RSP: 0x00007f153a79e280
RAX: 0x00007f1554addba8 RBX: 0x00007f153a79eab0 RCX: 0x0000000000000000
RDX: 0x00007f1554ade600 RDI: 0x00007f15551e8788 RSI: 0x0000000000000ae1
R8: 0x000000000000002b R9: 0x00007f153a79f038 R10: 0x00007f1554c0b9b0
R11: 0x00007f153a79e490 R12: 0x0000000000000ae1 R13: 0x0000000000000000
R14: 0x0000000000000000 R15: 0x000055ab732d7df0 EFL: 0x0000000000010206
-- C level backtrace information -------------------------------------------
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_print_backtrace+0x14) [0x7f1554f24961] /home/user/src/ruby-3.3.0/vm_dump.c:820
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_vm_bugreport) /home/user/src/ruby-3.3.0/vm_dump.c:1151
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_bug_for_fatal_signal+0x104) [0x7f1554d1c214] /home/user/src/ruby-3.3.0/error.c:1065
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(sigsegv+0x4f) [0x7f1554e700df] /home/user/src/ruby-3.3.0/signal.c:926
/lib/x86_64-linux-gnu/libc.so.6(0x7f1554842520) [0x7f1554842520]
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(RBASIC_CLASS+0x0) [0x7f1554f17ad8] ./include/ruby/internal/globals.h:178
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(gccct_method_search) /home/user/src/ruby-3.3.0/vm_eval.c:475
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_funcallv_scope) /home/user/src/ruby-3.3.0/vm_eval.c:1063
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_funcallv) /home/user/src/ruby-3.3.0/vm_eval.c:1084
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_inspect+0x19) [0x7f1554dc1569] /home/user/src/ruby-3.3.0/object.c:697
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(ruby__sfvextra+0x11a) [0x7f1554e7223a] /home/user/src/ruby-3.3.0/sprintf.c:1119
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(BSD_vfprintf+0xa69) [0x7f1554e73059] /home/user/src/ruby-3.3.0/vsnprintf.c:830
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(RBASIC_SET_CLASS_RAW+0x0) [0x7f1554e75b56] /home/user/src/ruby-3.3.0/sprintf.c:1168
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(ruby_vsprintf0) /home/user/src/ruby-3.3.0/sprintf.c:1169
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_enc_vsprintf+0x5d) [0x7f1554e75ecd] /home/user/src/ruby-3.3.0/sprintf.c:1195
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_sprintf+0x9d) [0x7f1554e7607d] /home/user/src/ruby-3.3.0/sprintf.c:1225
/home/user/dev/oss/async_ruby_test/rbnng/fiber_blocker/lib/fiber_blocker/fiber_blocker.so(block_fiber+0x4a) [0x7f1554ad430a] ../../../../ext/fiber_blocker/fiber_blocker.c:29
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(vm_cfp_consistent_p+0x0) [0x7f1554ef64b4] /home/user/src/ruby-3.3.0/vm_insnhelper.c:3490
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(vm_call_cfunc_with_frame_) /home/user/src/ruby-3.3.0/vm_insnhelper.c:3492
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(vm_call_cfunc_with_frame) /home/user/src/ruby-3.3.0/vm_insnhelper.c:3518
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(vm_call_cfunc_other) /home/user/src/ruby-3.3.0/vm_insnhelper.c:3544
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(vm_sendish+0x9e) [0x7f1554f06f87] /home/user/src/ruby-3.3.0/vm_insnhelper.c:5581
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(vm_exec_core) /home/user/src/ruby-3.3.0/insns.def:834
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_vm_exec+0x19a) [0x7f1554f0d1fa] /home/user/src/ruby-3.3.0/vm.c:2486
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_vm_invoke_proc+0x5f) [0x7f1554f12e0f] /home/user/src/ruby-3.3.0/vm.c:1728
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_fiber_start+0x1ba) [0x7f1554cf098a] /home/user/src/ruby-3.3.0/cont.c:2536
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(fiber_entry+0x20) [0x7f1554cf0d00] /home/user/src/ruby-3.3.0/cont.c:847
/home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_threadptr_root_fiber_setup) (null):0
</code></pre>
<p>This happens with the Async scheduler as well as with Ruby’s test scheduler. My minimal extension uses Ruby’s.</p>
<p>I hope I'm not missing something obvious. My C isn't very good.</p> Ruby master - Bug #20146 (Assigned): Code using Ractor with env `RUBY_MAX_CPU=1` ends with unreac...https://redmine.ruby-lang.org/issues/201462024-01-04T02:17:54Zshia (Sangyong Sim)
<a name="Reproducible-code"></a>
<h2 >Reproducible code<a href="#Reproducible-code" class="wiki-anchor">¶</a></h2>
<pre><code class="rb syntaxhl" data-language="rb"><span class="c1"># sample-code.rb</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span> <span class="p">{</span> <span class="mi">1</span> <span class="p">}</span>
</code></pre>
<pre><code class="bash syntaxhl" data-language="bash"><span class="nv">RUBY_MAX_CPU</span><span class="o">=</span>1 ruby sample-code.rb <span class="c"># This will not end with exit code 0</span>
<span class="nv">RUBY_MAX_CPU</span><span class="o">=</span>2 ruby sample-code.rb <span class="c"># This ends with exit code 0 as expected</span>
</code></pre>
<a name="Expected"></a>
<h2 >Expected<a href="#Expected" class="wiki-anchor">¶</a></h2>
<p>process with RUBY_MAX_CPU=1 exits successfully as same as RUBY_MAX_CPU more than 1.</p> Ruby master - Bug #20112 (Assigned): Ractors not working properly in ruby 3.3.0https://redmine.ruby-lang.org/issues/201122024-01-03T15:51:14Zariasdiniz (Aria Diniz)
<p>I recently installed Ruby 3.3.0, and noticed that some of my scripts that use Ractors started to struggle with performance. After doing some benchmarks, I noticed that, while Ractors seem to be working well on Ruby 3.2.2, they're not working properly on 3.3.0.</p>
<p>I'm using Ubuntu 22.04.3 LTS</p>
<p>Here is the benchmark code:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># frozen_string_literal: true</span>
<span class="nb">require</span> <span class="s1">'benchmark'</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span> <span class="p">{</span> <span class="ss">:warmup</span> <span class="p">}</span> <span class="k">if</span> <span class="k">defined?</span><span class="p">(</span><span class="no">Ractor</span><span class="p">)</span>
<span class="no">Benchmark</span><span class="p">.</span><span class="nf">bmbm</span> <span class="k">do</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Thread: "</span><span class="p">)</span> <span class="k">do</span>
<span class="n">threads</span> <span class="o">=</span> <span class="p">[]</span>
<span class="mi">8</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span>
<span class="n">threads</span> <span class="o"><<</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="mi">20000000</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span> <span class="o">|</span><span class="n">j</span><span class="o">|</span>
<span class="p">((</span><span class="n">i</span> <span class="o">*</span> <span class="mi">20000000</span><span class="p">)</span> <span class="o">+</span> <span class="n">j</span><span class="p">)</span><span class="o">**</span><span class="mi">2</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">threads</span><span class="p">.</span><span class="nf">each</span><span class="p">(</span><span class="o">&</span><span class="ss">:join</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Ractor: "</span><span class="p">)</span> <span class="k">do</span>
<span class="n">ractors</span> <span class="o">=</span> <span class="p">[]</span>
<span class="mi">0</span><span class="o">..</span><span class="mi">8</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span>
<span class="n">ractors</span> <span class="o"><<</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">k</span><span class="o">|</span>
<span class="mi">20000000</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span> <span class="o">|</span><span class="n">j</span><span class="o">|</span>
<span class="p">((</span><span class="n">k</span> <span class="o">*</span> <span class="mi">20000000</span><span class="p">)</span> <span class="o">+</span> <span class="n">j</span><span class="p">)</span><span class="o">**</span><span class="mi">2</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">ractors</span><span class="p">.</span><span class="nf">map</span><span class="p">(</span><span class="o">&</span><span class="ss">:take</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>Here is the results for Ruby 3.2.2:</p>
<p>Rehearsal --------------------------------------------<br>
Thread: 7.666909 0.001091 7.668000 ( 7.675266)<br>
Ractor: 19.318528 0.012017 19.330545 ( 2.505888)<br>
---------------------------------- total: 26.998545sec</p>
<pre><code> user system total real
</code></pre>
<p>Thread: 7.918141 0.004011 7.922152 ( 7.928772)<br>
Ractor: 19.366414 0.003954 19.370368 ( 2.517993)</p>
<p>Here is the results for Ruby 3.3.0:</p>
<p>Rehearsal --------------------------------------------<br>
Thread: 8.634152 0.010895 8.645047 ( 8.645104)<br>
Ractor: 100.172179 0.035985 100.208164 ( 15.213245)<br>
--------------------------------- total: 108.853211sec</p>
<pre><code> user system total real
</code></pre>
<p>Thread: 9.451236 0.004002 9.455238 ( 9.460132)<br>
Ractor: 118.463294 0.119942 118.583236 ( 18.462157)</p> Ruby master - Bug #20045 (Assigned): `TestDir#test_home` fails on i686https://redmine.ruby-lang.org/issues/200452023-12-07T09:28:07Zvo.x (Vit Ondruch)v.ondruch@tiscali.cz
<p>This is followup to <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: `TestFileExhaustive#test_expand_path_for_existent_username` and `TestDir#test_home` fails on i686 (Closed)" href="https://redmine.ruby-lang.org/issues/19147">#19147</a>. Testing on Fedora 38 and Fedora Rawhide, we are facing this test failure:</p>
<pre><code>$ tar xf build/SOURCES/ruby-3.2.2.tar.xz
$ cd ruby-3.2.2/
$ ./configure && make
... snip ...
---
Configuration summary for ruby version 3.2.2
* Installation prefix: /usr/local
* exec prefix: ${prefix}
* arch: i686-linux
* site arch: ${arch}
* RUBY_BASE_NAME: ruby
* ruby lib prefix: ${libdir}/${RUBY_BASE_NAME}
* site libraries path: ${rubylibprefix}/${sitearch}
* vendor path: ${rubylibprefix}/vendor_ruby
* target OS: linux
* compiler: gcc
* with thread: pthread
* with coroutine: x86
* enable shared libs: no
* dynamic library ext: so
* CFLAGS: ${optflags} ${debugflags} ${warnflags}
* LDFLAGS: -L. -fstack-protector-strong -rdynamic -Wl,-export-dynamic
* DLDFLAGS: -Wl,--compress-debug-sections=zlib
* optflags: -O3 -fno-fast-math
* debugflags: -ggdb3
* warnflags: -Wall -Wextra -Wdeprecated-declarations -Wdiv-by-zero -Wduplicated-cond -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wwrite-strings -Wold-style-definition \
-Wimplicit-fallthrough=0 -Wmissing-noreturn -Wno-cast-function-type -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-packed-bitfield-compat \
-Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wsuggest-attribute=format -Wsuggest-attribute=noreturn -Wunused-variable -Wundef
* strip command: strip -S -x
* install doc: rdoc
* MJIT support: yes
* YJIT support: no
* man page type: doc
---
... snip ...
$ LANG=C make test-all 'TESTS=-v -n /TestDir#test_home/'
config.status: creating ruby-runner.h
making mjit_build_dir.so
generating i686-linux-fake.rb
i686-linux-fake.rb updated
Run options:
--seed=10517
"--ruby=./miniruby -I./lib -I. -I.ext/common ./tool/runruby.rb --extout=.ext -- --disable-gems"
--excludes-dir=./test/excludes
--name=!/memory_leak/
-v
-n
/TestDir#test_home/
# Running tests:
[1/0] TestDir#test_home = 0.00 s
1) Error:
TestDir#test_home:
RuntimeError: can't set length of shared string
/builddir/ruby-3.2.2/test/ruby/test_dir.rb:557:in `expand_path'
/builddir/ruby-3.2.2/test/ruby/test_dir.rb:557:in `block in test_home'
Finished tests in 4.164691s, 0.2401 tests/s, 1.6808 assertions/s.
1 tests, 7 assertions, 0 failures, 1 errors, 0 skips
ruby -v: ruby 3.2.2 (2023-03-30 revision e51014f9c0) [i686-linux]
make: *** [uncommon.mk:855: yes-test-all] Error 1
</code></pre>
<p>Please note that having the <code>C</code> locale is essential. The test passes just fine with e.g. <code>C.UTF-8</code> locale.</p>
<p>We were able to reduce the test case to the following:</p>
<pre><code>$ whoami
mockbuild
$ echo 'File.expand_path("~mockbuild")' > test.rb
$ LANG=C RUBYLIB=/builddir/ruby-3.2.2/.ext/i686-linux LD_LIBRARY_PATH=. ./ruby --disable-gems test.rb
test.rb:1:in `expand_path': can't set length of shared string (RuntimeError)
from test.rb:1:in `<main>'
</code></pre>
<p>As I said earlier, the <code>LANG=C</code> is essential as well as the <code>RUBYLIB=/builddir/ruby-3.2.2/.ext/i386-linux</code>. Adding the path to <code>RUBYLIB</code> enables Ruby to load the following libraries:</p>
<pre><code>/builddir/ruby-3.2.2/.ext/i686-linux/enc/encdb.so
/builddir/ruby-3.2.2/.ext/i686-linux/enc/trans/transdb.so
</code></pre>
<p>And that makes the difference. Also, the <code>File.expand_path("~mockbuild")</code> must be in some file, replacing this by <code>-e 'File.expand_path("~mockbuild")'</code> does not reproduce the issue.</p>
<p>We also believe that this was introduced by <a href="https://github.com/ruby/ruby/pull/6699" class="external">https://github.com/ruby/ruby/pull/6699</a>, specifically by <a class="changeset" title="Transition shape when object's capacity changes This commit adds a `capacity` field to shapes, a..." href="https://redmine.ruby-lang.org/projects/ruby-master/repository/git/revisions/5246f4027ec574e77809845e1b1f7822cc2a5cef">git|5246f4027ec574e77809845e1b1f7822cc2a5cef</a> and fixed in master by <a class="changeset" title="Enable 5 size pools on 32 bit systems This commit will allow 32 bit systems to take advantage of..." href="https://redmine.ruby-lang.org/projects/ruby-master/repository/git/revisions/b4571097df4a6bd848f1195026d82a92f3a7f9d8">git|b4571097df4a6bd848f1195026d82a92f3a7f9d8</a>.</p>
<p>Unfortunately, we were not able to discover what is the mechanism behind this, why this depends on locale, why the test must be in file, why the string is shared etc. But I hope we have provided enough details for someone else more knowledgeable.</p>
<p>Some background for this issue is also available here:</p>
<p><a href="https://src.fedoraproject.org/rpms/ruby/pull-request/164" class="external">https://src.fedoraproject.org/rpms/ruby/pull-request/164</a></p> Ruby master - Bug #19996 (Assigned): `RUBY_MN_THREADS=1` triggers Action Cable unit test failureshttps://redmine.ruby-lang.org/issues/199962023-11-10T04:16:56Zyahonda (Yasuo Honda)yasuo.honda@gmail.com
<a name="Steps-to-reproduce"></a>
<h3 >Steps to reproduce<a href="#Steps-to-reproduce" class="wiki-anchor">¶</a></h3>
<ol>
<li>Install <code>ruby 3.3.0dev</code>
</li>
<li>Set <code>RUBY_MN_THREADS=1</code> environment variable</li>
<li>Follow these steps</li>
</ol>
<pre><code>git clone https://github.com/rails/rails
cd rails
rm Gemfile.lock
bundle install
cd actioncable
bin/test test/channel/base_test.rb test/subscription_adapter/redis_test.rb test/channel/test_case_test.rb test/subscription_adapter/redis_test.rb test/client_test.rb --seed 14800
</code></pre>
<a name="Expected-behavior"></a>
<h3 >Expected behavior<a href="#Expected-behavior" class="wiki-anchor">¶</a></h3>
<p>It should pass as not setting <code>RUBY_MN_THREADS</code>.</p>
<pre><code>$ unset RUBY_MN_THREADS
$ bin/test test/channel/base_test.rb test/subscription_adapter/redis_test.rb test/channel/test_case_test.rb test/subscription_adapter/redis_test.rb test/client_test.rb --seed 14800
/home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/minitest-5.20.0/lib/minitest.rb:3: warning: mutex_m which will no longer be part of the default gems since Ruby 3.4.0. Add mutex_m to your Gemfile or gemspec.
Run options: --seed 14800
# Running:
.........................................................................
Finished in 12.031310s, 6.0675 runs/s, 46.7115 assertions/s.
73 runs, 562 assertions, 0 failures, 0 errors, 0 skips
$
</code></pre>
<a name="Actual-behavior"></a>
<h3 >Actual behavior<a href="#Actual-behavior" class="wiki-anchor">¶</a></h3>
<p>It usually fails as follows.</p>
<pre><code>$ bin/test test/channel/base_test.rb test/subscription_adapter/redis_test.rb test/channel/test_case_test.rb test/subscription_adapter/redis_test.rb test/client_test.rb --seed 14800
/home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/minitest-5.20.0/lib/minitest.rb:3: warning: mutex_m which will no longer be part of the default gems since Ruby 3.4.0. Add mutex_m to your Gemfile or gemspec.
Run options: --seed 14800
# Running:
..................................................F
Failure:
RedisAdapterTest::AlternateConfiguration#test_channel_prefix [/home/yahonda/src/github.com/rails/rails/actioncable/test/subscription_adapter/common.rb:35]:
Expected #<Concurrent::Event:0x00007f0b2698d4f0 @__Lock__=#<Thread::Mutex:0x00007f0b26f8cab8>, @__Condition__=#<Thread::ConditionVariable:0x00007f0b26f8ca90>, @set=false, @iteration=0> to be set?.
bin/test test/subscription_adapter/channel_prefix.rb:6
.F
Failure:
RedisAdapterTest::AlternateConfiguration#test_multiple_broadcast [/home/yahonda/src/github.com/rails/rails/actioncable/test/subscription_adapter/common.rb:35]:
Expected #<Concurrent::Event:0x00007f0b2698a4d0 @__Lock__=#<Thread::Mutex:0x00007f0b26fac688>, @__Condition__=#<Thread::ConditionVariable:0x00007f0b26fac4f8>, @set=false, @iteration=0> to be set?.
bin/test test/subscription_adapter/common.rb:74
E
Error:
ClientTest#test_interacting_clients:
ThreadError: queue empty
<internal:thread_sync>:18:in `pop'
/home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:168:in `read_message'
/home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:241:in `block (2 levels) in test_interacting_clients'
/home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:218:in `block (2 levels) in concurrently'
/home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/promises.rb:1583:in `evaluate_to'
/home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/promises.rb:1766:in `block in on_resolvable'
/home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:352:in `run_task'
/home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:343:in `block (3 levels) in create_worker'
<internal:kernel>:187:in `loop'
/home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:334:in `block (2 levels) in create_worker'
/home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:333:in `catch'
/home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:333:in `block in create_worker'
/home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/promises.rb:1258:in `raise'
/home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/promises.rb:1258:in `wait_until_resolved!'
/home/yahonda/.rbenv/versions/trunk/lib/ruby/gems/3.3.0+0/gems/concurrent-ruby-1.2.2/lib/concurrent-ruby/concurrent/promises.rb:988:in `value!'
/home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:218:in `map'
/home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:218:in `concurrently'
/home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:240:in `block in test_interacting_clients'
/home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:90:in `with_puma_server'
/home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:234:in `test_interacting_clients'
bin/test test/client_test.rb:233
E
Error:
ClientTest#test_disappearing_client:
ThreadError: queue empty
<internal:thread_sync>:18:in `pop'
/home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:168:in `read_message'
/home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:275:in `block in test_disappearing_client'
/home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:90:in `with_puma_server'
/home/yahonda/src/github.com/rails/rails/actioncable/test/client_test.rb:273:in `test_disappearing_client'
bin/test test/client_test.rb:272
..................
Finished in 1323.812615s, 0.0551 runs/s, 0.3830 assertions/s.
73 runs, 507 assertions, 2 failures, 2 errors, 0 skips
$
</code></pre> Ruby master - Feature #19972 (Assigned): Install default/bundled gems into dedicated directorieshttps://redmine.ruby-lang.org/issues/199722023-10-25T15:30:22Zvo.x (Vit Ondruch)v.ondruch@tiscali.cz
<p>I think that the current situation, where the same directory (lets call it <code>Gem.default_dir</code>) is used for default/bundled gems as well as for user installed gems, is suboptimal. During the times, this has caused us quite some issue on Fedora. Historically, we redefined the <code>Gem.default_dir</code> to user home directory, to avoid the mixing of system gems and user installed gems. Unfortunately, with advent of default/bundled gems, we were facing issues that these gems were suddenly not listed, etc. I am realizing this issue in full once again since the "user install" RubyGems feature has landed <a href="https://github.com/rubygems/rubygems/pull/5327" class="external">1</a>. I also think that we have arrived to this situation by evolution, not by design.</p>
<p>Therefore my proposal is:</p>
<p>Keep the <code>Gem.default_dir</code> for user <code>gem install</code>ed gems and lets install default and bundled gems into separate dedicated directories. Have separate <code>Gem.bundled_gems_dir</code> and <code>Gem.default_gems_dir</code> structures.</p>
<p>Of course, if <code>Gem.default_dir == Gem.bundled_gems_dir == Gem.default_gems_dir</code>, we still can have the current layout.</p>
<p>I have a simple POC here:</p>
<p><a href="https://github.com/ruby/ruby/pull/8761" class="external">https://github.com/ruby/ruby/pull/8761</a></p>
<p>BTW I have reported it here, because I think that RubyGems provides all it is needed. So it is not RubyGems ticket after all. However, I believe that RubyGems could benefit from this long term and some simplifications/cleanups would be possible.</p> Ruby master - Feature #19908 (Assigned): Update to Unicode 15.1https://redmine.ruby-lang.org/issues/199082023-10-02T06:55:45Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<p>The Unicode 15.1 is released.</p>
<p>The current enc-unicode.rb seems to fail because of <code>Indic_Conjunct_break</code> properties with values.</p>
<p>I'm not sure how these properties should be handled well.<br>
<code>/\p{InCB_Liner}/</code> or <code>/\p{InCB=Liner}/</code> as the comments in that file?<br>
<a href="https://github.com/nobu/ruby/tree/unicode-15.1" class="external">https://github.com/nobu/ruby/tree/unicode-15.1</a> is the former.</p> Ruby master - Bug #19794 (Assigned): Ruby 3.2.2 fails to build on macOS Sonoma betashttps://redmine.ruby-lang.org/issues/197942023-08-02T05:08:15Zjhaungs (Jim Haungs)
<p>With Big Sur, Apple deprecated putting dylibs in /usr/local/lib. In Sonoma (beta 4), this directory has disappeared completely. However, ruby's configure script depends on its existence. So, virtually every ruby installer (RVM, rbenv, asdf, ruby-build, and even building from source tarball) fails.</p>
<p>When building ruby 3.2.2 from source, the configure step outputs the irritatingly useless "something wrong with LDFLAGS" error message and fails to build.</p>
<p>The solution was to <code>cd /usr/local; sudo mkdir lib</code> to create the missing lib directory under /usr/local.</p>
<p>It would be nice to remove this dependency from the configure script.</p> Ruby master - Feature #19465 (Assigned): [PATCH] reuse open(2) from rb_file_load_ok on POSIX-like...https://redmine.ruby-lang.org/issues/194652023-02-25T01:48:35Znormalperson (Eric Wong)normalperson@yhbt.net
<pre><code>When loading Ruby source files, we can save the result of
successful opens as open(2)/openat(2) are a fairly expensive
syscalls. This also avoids a time-of-check-to-time-of-use
(TOCTTOU) problem.
This reduces open(2) syscalls during `require'; but should be
most apparent when users have a small $LOAD_PATH. Users with
large $LOAD_PATH will benefit less since there'll be more
open(2) failures due to ENOENT.
With `strace -c -e openat ruby -e exit' under Linux, this
results in a ~14% reduction of openat(2) syscalls
(glibc uses openat(2) to implement open(2)).
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
0.00 0.000000 0 296 110 openat
0.00 0.000000 0 254 110 openat
Additionally, the introduction of `struct ruby_file_load_state'
may make future optimizations more apparent.
This change cannot benefit binary (.so) loading since the
dlopen(3) API requires a filename and I'm not aware of an
alternative that takes a pre-existing FD. In typical
situations, Ruby source files outnumber the mount of .so
files.
I've only tested this lightly on small apps since I don't have
large codebases to test on. However, I think organizing various
on-stack variables into `struct ruby_file_load_state' can be
beneficial if we end up using io-uring on Linux.
</code></pre> Ruby master - Feature #19422 (Assigned): Make `--enabled-shared` mandatory on macOShttps://redmine.ruby-lang.org/issues/194222023-02-07T08:14:26Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<p>From the troubles around linker on macOS, I propose <code>--enable-shared</code> option mandatory on macOS.<br>
This patch enables the option by default, and abort if <code>--disable-shared</code> option is given explicitly.</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git i/configure.ac w/configure.ac
index 7db2ab5257c..923ac7d1199 100644
</span><span class="gd">--- i/configure.ac
</span><span class="gi">+++ w/configure.ac
</span><span class="p">@@ -504,6 +504,11 @@</span> AS_CASE(["$target_os"],
rb_cv_binary_elf=no
: ${enable_shared=yes}
],
<span class="gi">+[darwin*], [
+ AS_IF([test "${enable_shared=yes}" = no], [
+ AC_MSG_ERROR([--disable-shared is not supported on this platform])
+ ])
+],
</span> [hiuxmpp*], [AC_DEFINE(__HIUX_MPP__)]) # by TOYODA Eizi <toyoda@npd.kishou.go.jp>
AC_PROG_LN_S
<span class="p">@@ -3055,14 +3060,7 @@</span> AC_SUBST(EXTOBJS)
: ${LDFLAGS=""}
: ${LIBPATHENV=DYLD_FALLBACK_LIBRARY_PATH}
: ${PRELOADENV=DYLD_INSERT_LIBRARIES}
<span class="gd">- AS_IF([test x"$enable_shared" = xyes], [
- # Resolve symbols from libruby.dylib when --enable-shared
- EXTDLDFLAGS='$(LIBRUBYARG_SHARED)'
- ], [test "x$EXTSTATIC" = x], [
- # When building exts as bundles, a mach-o bundle needs to know its loader
- # program to bind symbols from the ruby executable
- EXTDLDFLAGS="-bundle_loader '\$(BUILTRUBY)'"
- ])
</span><span class="gi">+ EXTDLDFLAGS='$(LIBRUBYARG_SHARED)'
</span> rb_cv_dlopen=yes],
[aix*], [ : ${LDSHARED='$(CC)'}
AS_IF([test "$GCC" = yes], [
<span class="p">@@ -3356,10 +3354,6 @@</span> AS_IF([test x"$cross_compiling" = xyes], [
AC_SUBST(XRUBY_RUBYLIBDIR)
AC_SUBST(XRUBY_RUBYHDRDIR)
PREP='$(arch)-fake.rb'
<span class="gd">- AS_CASE(["$enable_shared:$EXTSTATIC:$target_os"], [no::darwin*], [
- # darwin target requires miniruby for linking ext bundles
- PREP="$PREP"' miniruby$(EXEEXT)'
- ])
</span> RUNRUBY_COMMAND='$(MINIRUBY) -I`cd $(srcdir)/lib; pwd`'
RUNRUBY='$(RUNRUBY_COMMAND)'
XRUBY='$(MINIRUBY)'
</code></pre> Ruby master - Bug #19410 (Assigned): If move from ractor fails with error, some objects are left ...https://redmine.ruby-lang.org/issues/194102023-02-03T20:02:50Zluke-gru (Luke Gruber)luke.gru@gmail.com
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">r</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">obj</span> <span class="o">=</span> <span class="n">receive</span>
<span class="k">end</span>
<span class="n">a</span> <span class="o">=</span> <span class="no">Object</span><span class="p">.</span><span class="nf">new</span>
<span class="n">obj</span> <span class="o">=</span> <span class="p">[</span><span class="n">a</span><span class="p">,</span> <span class="nb">proc</span> <span class="p">{</span> <span class="p">}]</span>
<span class="k">begin</span>
<span class="n">r</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="ss">move: </span><span class="kp">true</span><span class="p">)</span>
<span class="k">rescue</span> <span class="o">=></span> <span class="n">e</span>
<span class="nb">puts</span> <span class="s2">"couldn't move"</span>
<span class="k">end</span>
<span class="nb">p</span> <span class="n">a</span> <span class="c1"># a is moved, this errors out. But it's not really moved because the other ractor can't access it. It's in limbo :)</span>
<span class="n">r</span> <span class="o"><<</span> <span class="ss">:end</span>
<span class="n">r</span><span class="p">.</span><span class="nf">take</span>
</code></pre>
<p>This might be tricky to fix, as it requires some sort of commit function for moving objects after every object is checked for ability to move.</p> Ruby master - Bug #19408 (Assigned): Object no longer frozen after moved from a ractorhttps://redmine.ruby-lang.org/issues/194082023-02-03T18:55:10Zluke-gru (Luke Gruber)luke.gru@gmail.com
<p>I think frozen objects should still be frozen after a move.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">r</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">obj</span> <span class="o">=</span> <span class="n">receive</span>
<span class="nb">p</span> <span class="n">obj</span><span class="p">.</span><span class="nf">frozen?</span> <span class="c1"># should be true but is false</span>
<span class="nb">p</span> <span class="n">obj</span>
<span class="k">end</span>
<span class="n">obj</span> <span class="o">=</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">freeze</span>
<span class="n">r</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="ss">move: </span><span class="kp">true</span><span class="p">)</span>
<span class="n">r</span><span class="p">.</span><span class="nf">take</span>
</code></pre> Ruby master - Bug #19407 (Assigned): 2 threads taking from current ractor will hang foreverhttps://redmine.ruby-lang.org/issues/194072023-02-03T18:43:11Zluke-gru (Luke Gruber)luke.gru@gmail.com
<p>In the current implementation of Ractors, it's possible to <code>take</code> from the current ractor. This could be useful<br>
when co-ordinating threads:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">t</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">obj</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">take</span>
<span class="nb">p</span> <span class="n">obj</span> <span class="c1"># do some work with obj</span>
<span class="k">end</span>
<span class="n">t0</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">obj</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">take</span>
<span class="nb">p</span> <span class="n">obj</span> <span class="c1"># do some work with obj</span>
<span class="k">end</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">yield</span> <span class="ss">:go</span>
</code></pre>
<p>However it hangs forever:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">t</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">obj</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">take</span>
<span class="nb">p</span> <span class="n">obj</span>
<span class="k">end</span>
<span class="n">t0</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">obj</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">take</span>
<span class="nb">p</span> <span class="n">obj</span>
<span class="k">end</span>
<span class="nb">sleep</span> <span class="mf">0.5</span>
</code></pre>
<p>Should "self-take" be disabled, or was it designed to allow it but this is just a bug?</p> Ruby master - Bug #19383 (Assigned): Time.now.zone encoding for German display language in Window...https://redmine.ruby-lang.org/issues/193832023-01-26T20:52:24Zstringsn88keys (Thomas Powell)
<p>OS:<br>
Verified on Windows 10 and Windows Server 2022 and Ruby 2.7.7 through 3.1.3</p>
<p>Display language:<br>
Verified on German, but may impact other languages in which Time.now.zone returns characters that aren't [A-Za-z].</p>
<p>Time zone:<br>
CET (UTC +01:00) Amsterdam, Berlin, ...</p>
<p>Time.now.zone # => "Mitteleuro\xE3ische Zeit"<br>
Time.now.zone.encoding # => #<a href="Encoding:IBM437" class="external">Encoding:IBM437</a><br>
puts Time.now.zone # => "Mitteleurop∑ische Zeit" (should be "Mitteleuropäische Zeit")<br>
Time.now.zone.encode(Encoding::UTF_8) # => "Mitteleurop∑ische Zeit"</p>
<p>Doing a force_encoding on all encodings in Encoding.list reveals that ISO-8859-(1..16) and Windows-125(0,2,4,7) work to coerce the ä out of the time zone string:<br>
Time.now.zone.force_encoding(Encoding::WINDOWS_1252) # => "Mitteleuro\xE3ische Zeit"<br>
... but ...<br>
Time.now.zone.force_encoding(Encoding::WINDOWS_1252).encode(Encoding::UTF_8) #=> "Mitteleuropäische Zeit"</p>
<p>Related issue: This improper encoding/rendering caused Ohai's JSON output to be unparseable. Workaround was forcing to Windows-1252.<br>
<a href="https://github.com/chef/ohai/pull/1781" class="external">https://github.com/chef/ohai/pull/1781</a></p> Ruby master - Bug #19378 (Assigned): Windows: Use less syscalls for faster require of big gemshttps://redmine.ruby-lang.org/issues/193782023-01-26T07:02:23Zaidog (Andi Idogawa)andi@idogawa.com
<p>Hello 🙂</p>
<a name="Problem"></a>
<h2 >Problem<a href="#Problem" class="wiki-anchor">¶</a></h2>
<p>require is slow on windows for big gems. (example: require 'gtk3'=> 3 seconds+). This is a problem for people who want to make cross platform GUI apps with ruby.</p>
<a name="Possible-Reason"></a>
<h2 >Possible Reason<a href="#Possible-Reason" class="wiki-anchor">¶</a></h2>
<p>As touched on in <a href="https://bugs.ruby-lang.org/issues/15797" class="external">#15797</a> it seems like require uses realpath, which is emulated on windows. It checks every parent directory. The same syscalls run many times.</p>
<a name="Testfile"></a>
<h2 >Testfile<a href="#Testfile" class="wiki-anchor">¶</a></h2>
<p>C:\tmp\speedtest\testrequire.rb:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="n">__dir__</span> <span class="o">+</span> <span class="s2">"/helloworld1.rb"</span>
<span class="nb">require</span> <span class="n">__dir__</span> <span class="o">+</span> <span class="s2">"/helloworld2.rb"</span>
</code></pre>
<pre><code class="shell syntaxhl" data-language="shell">ruby <span class="nt">--disable-gems</span> C:<span class="se">\t</span>mp<span class="se">\s</span>peedtest<span class="se">\t</span>estrequire.rb
</code></pre>
<a name="Syscalls-per-FileDirectory"></a>
<h3 >Syscalls per File/Directory:<a href="#Syscalls-per-FileDirectory" class="wiki-anchor">¶</a></h3>
<ol>
<li>CreateFile</li>
<li>QueryInformationVolume</li>
<li>QueryIdInformation</li>
<li>QueryAllInformationFile</li>
<li>QueryNameInformationFile</li>
<li>QueryNameInformationFile</li>
<li>QueryNormalizedNameInformationFile</li>
<li>CloseFile</li>
</ol>
<a name="FilesDirectories-checked"></a>
<h3 >Files/Directories checked<a href="#FilesDirectories-checked" class="wiki-anchor">¶</a></h3>
<ol>
<li>C:\tmp</li>
<li>C:\tmp\speedtest</li>
<li>C:\tmp\speedtest\helloworld1.rb</li>
<li>C:\tmp</li>
<li>C:\tmp\speedtest</li>
<li>C:\tmp\speedtest\helloworld2.rb</li>
</ol>
<p>For two required files Ruby had to do 8*6 = <strong>48</strong> syscalls.<br>
The syscalls orginate from rb_w32_reparse_symlink_p / lstat</p>
<p>Rubygems live in subfolders with 9+ parts: "C:\Ruby32-x64\lib\ruby\gems\3.2.0\gems\glib2-4.0.8\lib\glib2\variant.rb"<br>
Each file takes 8 * 9 = <strong>72</strong>+ calls. For variant.rb it is <strong>80</strong> calls.<br>
The result for the syscalls don't change in such a short time, so it should be possible to cache it.</p>
<p>With require_relative it's twice as many calls.</p>
<a name="Other-testcases"></a>
<h2 >Other testcases<a href="#Other-testcases" class="wiki-anchor">¶</a></h2>
<p>Same result:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">File</span><span class="p">.</span><span class="nf">realpath</span> <span class="n">__dir__</span> <span class="o">+</span> <span class="s2">"/helloworld1.rb"</span>
<span class="no">File</span><span class="p">.</span><span class="nf">realpath</span> <span class="n">__dir__</span> <span class="o">+</span> <span class="s2">"/helloworld2.rb"</span>
</code></pre>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">File</span><span class="p">.</span><span class="nf">stat</span> <span class="n">__dir__</span> <span class="o">+</span> <span class="s2">"/helloworld1.rb"</span>
<span class="no">File</span><span class="p">.</span><span class="nf">stat</span> <span class="n">__dir__</span> <span class="o">+</span> <span class="s2">"/helloworld2.rb"</span>
</code></pre>
<p>It does not happen in $LOAD_PATH.resolve_feature_path(<strong>dir</strong> + "/helloworld1.rb")</p>
<a name="Request"></a>
<h2 >Request<a href="#Request" class="wiki-anchor">¶</a></h2>
<p>Would it be possible to cache the stat calls when using require?<br>
I tried to implement a cache inside the ruby source code, but failed.<br>
If not, is there now a way to combine ruby files into one?</p>
<p>I previously talked about require here: <a href="https://bugs.ruby-lang.org/issues/19325#note-11" class="external">YJIT: Windows support lacking.</a></p>
<a name="How-to-reproduce"></a>
<h2 >How to reproduce<a href="#How-to-reproduce" class="wiki-anchor">¶</a></h2>
<p>Ruby versions: At least 3.0+, most likely older ones too.<br>
Tested using Ruby Installer 3.1 and 3.2.<br>
<a href="https://learn.microsoft.com/en-us/sysinternals/downloads/procmon" class="external">Procmon Software by Sysinternals</a></p> Ruby master - Bug #19374 (Assigned): Issue with Ractor.make_shareable with curried procshttps://redmine.ruby-lang.org/issues/193742023-01-24T12:40:33Zluke-gru (Luke Gruber)luke.gru@gmail.com
<p>This works, but shouldn't:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Worker</span>
<span class="k">def</span> <span class="nf">start</span><span class="p">(</span><span class="o">&</span><span class="n">blk</span><span class="p">)</span>
<span class="n">blk</span> <span class="o">=</span> <span class="n">blk</span><span class="p">.</span><span class="nf">curry</span> <span class="c1"># bug in ruby allows sharing of non-shareable proc</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">make_shareable</span><span class="p">(</span><span class="n">blk</span><span class="p">)</span>
<span class="vi">@ractor</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">blk</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">b</span><span class="o">|</span>
<span class="n">main</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="nf">call</span>
<span class="nb">p</span> <span class="s2">"from ractor: </span><span class="si">#{</span><span class="n">main</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">work</span>
<span class="vi">@ractor</span><span class="p">.</span><span class="nf">take</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">worker</span> <span class="o">=</span> <span class="no">Worker</span><span class="p">.</span><span class="nf">new</span>
<span class="n">a</span> <span class="o">=</span> <span class="nb">self</span> <span class="c1"># unshareable main object</span>
<span class="nb">p</span> <span class="s2">"from main: </span><span class="si">#{</span><span class="n">a</span><span class="si">}</span><span class="s2">"</span>
<span class="n">worker</span><span class="p">.</span><span class="nf">start</span> <span class="p">{</span> <span class="n">a</span> <span class="p">}</span>
<span class="n">worker</span><span class="p">.</span><span class="nf">work</span>
</code></pre>
<p>The curried proc has a reference to the original proc and it's not checked for shareability.</p> Ruby master - Bug #19372 (Assigned): Proc objects are not traversed for shareable check during Ra...https://redmine.ruby-lang.org/issues/193722023-01-23T19:23:33Zluke-gru (Luke Gruber)luke.gru@gmail.com
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Proc</span>
<span class="nb">attr_accessor</span> <span class="ss">:obj1</span>
<span class="k">def</span> <span class="nf">initialize</span>
<span class="vi">@obj1</span> <span class="o">=</span> <span class="no">Object</span><span class="p">.</span><span class="nf">new</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="nb">p</span> <span class="o">=</span> <span class="kp">true</span><span class="p">.</span><span class="nf">instance_eval</span> <span class="p">{</span> <span class="no">Proc</span><span class="p">.</span><span class="nf">new</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s2">"hi"</span> <span class="p">}</span> <span class="p">}</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">make_shareable</span><span class="p">(</span><span class="nb">p</span><span class="p">)</span>
<span class="nb">p</span> <span class="s2">"Obj1 frozen?"</span><span class="p">,</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">shareable?</span><span class="p">(</span><span class="nb">p</span><span class="p">.</span><span class="nf">obj1</span><span class="p">)</span>
<span class="no">P</span> <span class="o">=</span> <span class="nb">p</span>
<span class="n">r</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">pp</span> <span class="o">=</span> <span class="no">P</span>
<span class="nb">p</span> <span class="n">pp</span><span class="p">.</span><span class="nf">obj1</span> <span class="c1"># gives error in debug builds (rb_ractor_confirm_belonging rb_bug() call)</span>
<span class="k">end</span>
</code></pre> Ruby master - Bug #19369 (Assigned): Small corner-case issue that breaks Ractor isolation: change...https://redmine.ruby-lang.org/issues/193692023-01-23T01:28:22Zluke-gru (Luke Gruber)luke.gru@gmail.com
<p>I was looking into how objects are traversed for deep cloning and I came up with a way to break it. I don't think it'll ever happen in real life so it's not really an issue, just<br>
an interesting case. Run with warnings disabled.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">obj</span> <span class="o">=</span> <span class="no">Object</span><span class="p">.</span><span class="nf">new</span>
<span class="nb">p</span> <span class="s2">"unshareable obj:"</span><span class="p">,</span> <span class="n">obj</span>
<span class="no">UNSHAREABLE</span> <span class="o">=</span> <span class="n">obj</span>
<span class="no">GO</span> <span class="o">=</span> <span class="kp">false</span>
<span class="no">SET</span> <span class="o">=</span> <span class="kp">false</span>
<span class="k">class</span> <span class="nc">Object</span>
<span class="nb">attr_accessor</span> <span class="ss">:unshareable</span>
<span class="k">def</span> <span class="nf">initialize_clone</span><span class="p">(</span><span class="n">orig</span><span class="p">)</span>
<span class="nb">puts</span> <span class="s2">"Clone called for </span><span class="si">#{</span><span class="n">orig</span><span class="p">.</span><span class="nf">inspect</span><span class="si">}</span><span class="s2">, self = </span><span class="si">#{</span><span class="nb">self</span><span class="p">.</span><span class="nf">inspect</span><span class="si">}</span><span class="s2">"</span>
<span class="n">_self</span> <span class="o">=</span> <span class="nb">self</span>
<span class="k">if</span> <span class="n">orig</span> <span class="o">==</span> <span class="no">UNSHAREABLE</span>
<span class="n">t</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="nb">puts</span> <span class="s2">"In thread"</span>
<span class="no">Thread</span><span class="p">.</span><span class="nf">pass</span> <span class="k">until</span> <span class="no">GO</span>
<span class="nb">puts</span> <span class="s2">"Setting unshareable!"</span>
<span class="c1"># this must be done in separate thread to bypass object traversal deep-cloning</span>
<span class="n">_self</span><span class="p">.</span><span class="nf">unshareable</span> <span class="o">=</span> <span class="no">UNSHAREABLE</span>
<span class="no">Object</span><span class="p">.</span><span class="nf">const_set</span><span class="p">(</span><span class="ss">:SET</span><span class="p">,</span> <span class="kp">true</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">super</span><span class="p">(</span><span class="n">orig</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">r</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">o</span><span class="o">|</span>
<span class="nb">puts</span> <span class="s2">"from r</span><span class="si">#{</span><span class="no">Ractor</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">object_id</span><span class="si">}</span><span class="s2"> obj </span><span class="si">#{</span><span class="n">o</span><span class="p">.</span><span class="nf">inspect</span><span class="si">}</span><span class="s2">"</span>
<span class="no">GO</span> <span class="o">=</span> <span class="kp">true</span>
<span class="kp">loop</span> <span class="k">until</span> <span class="no">SET</span>
<span class="nb">p</span> <span class="s2">"from ractor, got unshareable:"</span><span class="p">,</span> <span class="n">o</span><span class="p">.</span><span class="nf">unshareable</span>
<span class="k">end</span>
<span class="n">r</span><span class="p">.</span><span class="nf">take</span>
</code></pre> Ruby master - Bug #19368 (Assigned): Small issue with isolated procs and evalhttps://redmine.ruby-lang.org/issues/193682023-01-22T17:40:38Zluke-gru (Luke Gruber)luke.gru@gmail.com
<pre><code>a = Object.new # non-shareable
prok = Ractor.current.instance_eval do
Proc.new do
eval('a')
end
end
prok.call # this should work, we're in the main ractor and the proc is not isolated
Ractor.make_shareable(prok) # this doesn't currently work, but I think it should. It gives Ractor::IsolationError. See below for reasoning on why I think it should work.
# A flag seems to be set on the proc after it's run and accesses outers...
</code></pre>
<p>Because this work fine:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">a</span> <span class="o">=</span> <span class="no">Object</span><span class="p">.</span><span class="nf">new</span> <span class="c1"># non-shareable</span>
<span class="n">prok</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">instance_eval</span> <span class="k">do</span>
<span class="no">Proc</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="nb">eval</span><span class="p">(</span><span class="s1">'a'</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">make_shareable</span><span class="p">(</span><span class="n">prok</span><span class="p">)</span> <span class="c1"># this works, and it's okay because we get a different error when actually running the shareable proc inside a ractor that accesses outers through eval.</span>
</code></pre> Ruby master - Bug #19367 (Assigned): Issue with ractor local storage APIhttps://redmine.ruby-lang.org/issues/193672023-01-22T14:46:45Zluke-gru (Luke Gruber)luke.gru@gmail.com
<p>In a non-main ractor, you can do Ractor.main[:key] = 'val', but it only affects storage for Ractor.current, not Ractor.main (which is good!).<br>
I think it should throw a RuntimeError if trying to get/set ractor-local storage for non-current ractor.</p>
<p>Patch coming.</p> Ruby master - Bug #19364 (Assigned): Issue with tracepoint enable/disable across ractorshttps://redmine.ruby-lang.org/issues/193642023-01-21T22:54:58Zluke-gru (Luke Gruber)luke.gru@gmail.com
<p>This sometimes segfaults:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">test_enable_disable_in_multiple_ractors_with_target</span>
<span class="n">rs</span> <span class="o">=</span> <span class="p">[]</span>
<span class="mi">100</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span>
<span class="c1"># setup new iseqs</span>
<span class="no">Kernel</span><span class="p">.</span><span class="nf">define_method</span> <span class="ss">:"my_method_to_change_for_tracing_</span><span class="si">#{</span><span class="n">i</span><span class="si">}</span><span class="ss">"</span> <span class="k">do</span>
<span class="kp">true</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="mi">100</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span>
<span class="n">rs</span> <span class="o"><<</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">j</span><span class="o">|</span>
<span class="n">meth</span> <span class="o">=</span> <span class="ss">:"my_method_to_change_for_tracing_</span><span class="si">#{</span><span class="n">j</span><span class="si">}</span><span class="ss">"</span>
<span class="n">tp</span> <span class="o">=</span> <span class="no">TracePoint</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">:line</span><span class="p">)</span> <span class="p">{</span> <span class="p">}</span> <span class="c1"># local to ractor</span>
<span class="mi">100</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span>
<span class="n">tp</span><span class="p">.</span><span class="nf">enable</span><span class="p">(</span><span class="ss">target: </span><span class="nb">method</span><span class="p">(</span><span class="n">meth</span><span class="p">))</span> <span class="c1"># change iseq internals of given method, should be done with lock</span>
<span class="n">tp</span><span class="p">.</span><span class="nf">disable</span> <span class="c1"># disable hooks should hold lock too, changes method definition internals</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">rs</span><span class="p">.</span><span class="nf">each</span><span class="p">(</span><span class="o">&</span><span class="ss">:take</span><span class="p">)</span> <span class="c1"># shouldn't raise</span>
<span class="k">end</span>
<span class="n">test_enable_disable_in_multiple_ractors_with_target</span><span class="p">()</span>
</code></pre>
<p>Changing iseq internals is done without the VM lock. This is true in Tracepoint#enable and Tracepoint#disable methods.<br>
I have a patch coming.</p> Ruby master - Bug #19338 (Assigned): Ruby hangs when ouputting warnings inside ractor with VM loc...https://redmine.ruby-lang.org/issues/193382023-01-14T18:15:37Zluke-gru (Luke Gruber)luke.gru@gmail.com
<p>This code causes Ruby to hang:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">rs</span> <span class="o">=</span> <span class="p">[]</span>
<span class="mi">2</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span>
<span class="n">rs</span> <span class="o"><<</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="no">MYCONSTANT</span> <span class="o">=</span> <span class="mi">2</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">rs</span><span class="p">.</span><span class="nf">each</span><span class="p">(</span><span class="o">&</span><span class="ss">:take</span><span class="p">)</span>
</code></pre>
<p>There is a problem when the warning is being outputted with multiple ractors. A thread is calling RB_VM_LOCK() while holding the VM lock in ractor.c (ractor_check_blocking())</p>
<p>If the code is changed to RB_VM_LOCK_ENTER() and RB_VM_LOCK_LEAVE() then it fixes it, but I don't know if there's a better way.</p>
<p>Thanks!</p> Ruby master - Feature #19326 (Assigned): Please add a better API for passing a Proc to a Ractorhttps://redmine.ruby-lang.org/issues/193262023-01-08T19:31:09Zsdwolfz (Codruț Gușoi)
<p>Example 1:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Worker</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="vi">@block</span> <span class="o">=</span> <span class="n">block</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">run</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="vi">@block</span><span class="p">,</span> <span class="o">&</span><span class="ss">:call</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">worker</span> <span class="o">=</span> <span class="no">Worker</span><span class="p">.</span><span class="nf">new</span> <span class="p">{</span> <span class="mi">1</span> <span class="p">}</span>
<span class="nb">puts</span> <span class="n">worker</span><span class="p">.</span><span class="nf">run</span><span class="p">.</span><span class="nf">take</span>
</code></pre>
<p>Errors with:</p>
<pre><code><internal:ractor>:271:in `new': allocator undefined for Proc (TypeError)
from scripts/run.rb:9:in `run'
from scripts/run.rb:14:in `<main>'
</code></pre>
<p>Example 2:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Worker</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="vi">@block</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">make_shareable</span><span class="p">(</span><span class="n">block</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">run</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="vi">@block</span><span class="p">,</span> <span class="o">&</span><span class="ss">:call</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">worker</span> <span class="o">=</span> <span class="no">Worker</span><span class="p">.</span><span class="nf">new</span> <span class="p">{</span> <span class="mi">1</span> <span class="p">}</span>
<span class="nb">puts</span> <span class="n">worker</span><span class="p">.</span><span class="nf">run</span><span class="p">.</span><span class="nf">take</span>
</code></pre>
<p>Errors with:</p>
<pre><code><internal:ractor>:820:in `make_shareable': Proc's self is not shareable: #<Proc:0x00007f00394c38b8 scripts/run.rb:13> (Ractor::IsolationError)
from scripts/run.rb:5:in `initialize'
from scripts/run.rb:13:in `new'
from scripts/run.rb:13:in `<main>'
</code></pre>
<p>Example 3:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Worker</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="vi">@block</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">make_shareable</span><span class="p">(</span><span class="n">block</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">run</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="vi">@block</span><span class="p">,</span> <span class="o">&</span><span class="ss">:call</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">worker</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">instance_eval</span> <span class="p">{</span> <span class="no">Worker</span><span class="p">.</span><span class="nf">new</span> <span class="p">{</span> <span class="mi">1</span> <span class="p">}</span> <span class="p">}</span>
<span class="nb">puts</span> <span class="n">worker</span><span class="p">.</span><span class="nf">run</span><span class="p">.</span><span class="nf">take</span>
</code></pre>
<p>Works, but having <code>Ractor.current.instance_eval</code> as a wrapper around the block is not ideal, as Ractor is supposed to be only an implementation detail in Worker.</p>
<p>I know about <a href="https://bugs.ruby-lang.org/issues/18243" class="external">https://bugs.ruby-lang.org/issues/18243</a> and the discussion around <code>proc.bind(nil)</code>. That would actually be ideal, as for the purposes if why I want this functionality I don't care what <code>self</code> is in a block, and the less it has access to the better.</p>
<p>The general idea of Worker is to have a Ractor be able to lazily execute an arbitrary proc. And all the bindings it would need would be passed explicitly, either through <code>args</code> in the constructor or through <code>send</code>/<code>receive</code>, so <code>self</code> would really not matter.</p>
<p>The benefit: this would make it so concurrent code can be more easily be implemented with Ractors as currently you can execute an arbitrary proc by passing it to a Thread (but you don't get the nice data isolation).</p> Ruby master - Feature #19325 (Assigned): YJIT: Windows support lacking.https://redmine.ruby-lang.org/issues/193252023-01-08T18:09:41Zdsisnero (Dominic Sisneros)dsisnero@gmail.com
<p>Ruby's support on windows has always been second class. With some of the recent decisions, windows support is falling even more behind. Recent developments in mjit and yjit that exclude windows are two glaring issues that should be corrected. Googling 'percent of windows vs other operating systems' and it shows windows has a share of 76%. Ceding that users to python and other programming languages has to be one of the reasons python continues get more market share from ruby. With rust having first class windows support and threading support, is there a reason why yjit is not able to work on windows? Also, windows compiler support has matured enough and vcpkg support has evolved enough that it seems it should be possible to finally get a ruby version without having to use msys2. Even Crystal language has a version that runs on windows without needing msys2.</p> Ruby master - Feature #19317 (Assigned): Unicode ICU Full case mappinghttps://redmine.ruby-lang.org/issues/193172023-01-06T15:05:39Znoraj (Alexandre ZANNI)
<p>As announced in <a href="https://docs.ruby-lang.org/en/master/case_mapping_rdoc.html#label-Default+Case+Mapping" class="external">Case Mapping</a>, Ruby support for Unicode case mapping is not complete yet.</p>
<p>Unicode supports in Ruby is pretty awesome, it works by default nearly everywhere, things are implemented the right way and works as expected by the UTRs.</p>
<p>But some features are still missing.</p>
<p>To reach <a href="https://unicode-org.github.io/icu/userguide/transforms/casemappings.html#full-language-specific-case-mapping" class="external">ICU Full Case Mapping support</a>, a few points need to be enhanced.</p>
<a name="context-sensitive-case-mapping"></a>
<h3 >context-sensitive case mapping<a href="#context-sensitive-case-mapping" class="wiki-anchor">¶</a></h3>
<ul class="task-list">
<li class="task-list-item">
<input type="checkbox" class="task-list-item-checkbox" disabled> cf. <a href="https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf" class="external">Table 3-17 (Context Specification for Casing) of the Unicode standard</a> and <a href="https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt" class="external">ucd/SpecialCasing.txt</a>.</li>
</ul>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="s2">"ΣΣ"</span><span class="p">.</span><span class="nf">downcase</span> <span class="c1"># returns σσ instead of σς</span>
</code></pre>
<p>Output examples in ECMAScript:</p>
<pre><code>Σ ➡️ σ
Σa ➡️ σa
aΣ ➡️ aς
aΣa ➡️ aσa
ΣA ➡️ σa
aΣ a ➡️ aς a
Σ1 ➡️ σ1
aΣ1 ➡️ aς1
ΣΣ ➡️ σς
</code></pre>
<a name="language-sensitive-case-mapping"></a>
<h2 >language-sensitive case mapping<a href="#language-sensitive-case-mapping" class="wiki-anchor">¶</a></h2>
<ul class="task-list">
<li class="task-list-item">
<input type="checkbox" class="task-list-item-checkbox" disabled> Lithuanian rules</li>
<li class="task-list-item">
<input type="checkbox" class="task-list-item-checkbox" checked disabled> Turkish and Azeri</li>
</ul>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="s2">"I"</span><span class="p">.</span><span class="nf">downcase</span> <span class="c1"># => "i"</span>
<span class="s2">"I"</span><span class="p">.</span><span class="nf">downcase</span><span class="p">(</span><span class="ss">:turkic</span><span class="p">)</span> <span class="c1"># => "ı"</span>
<span class="s2">"I</span><span class="se">\u</span><span class="s2">0307"</span><span class="p">.</span><span class="nf">upcase</span> <span class="c1"># => "İ"</span>
<span class="s2">"I</span><span class="se">\u</span><span class="s2">0307"</span><span class="p">.</span><span class="nf">upcase</span><span class="p">(</span><span class="ss">:lithuanian</span><span class="p">)</span> <span class="c1"># => "İ" instead of "I"</span>
</code></pre>
<ul class="task-list">
<li class="task-list-item">
<input type="checkbox" class="task-list-item-checkbox" disabled> using some standard locale / language codes</li>
</ul>
<p>Also, it's true that for now there are only a few language-sensitive rules (for Lithuanian, Turkish and Azeri) but why:</p>
<ul>
<li>adding a <code>:turkic</code> symbol and not a <code>:azeri</code>?</li>
<li>using full english arbitrary (why <code>turkic</code> and not <code>turkish</code>?) language name rather than some <a href="https://unicode-org.github.io/icu/userguide/locale/" class="external">ICU locale IDs</a>?
<ul>
<li>Language code ISO-639 standard</li>
<li>Script code Unicode ISO 15924 Registry</li>
<li>country code ISO-3166 standard</li>
</ul>
</li>
</ul>
<p>So I would rather see something like that</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="s2">"placeholder"</span><span class="p">.</span><span class="nf">upcase</span><span class="p">(</span><span class="ss">locale: :tr_TR</span><span class="p">)</span>
<span class="s2">"placeholder"</span><span class="p">.</span><span class="nf">upcase</span><span class="p">(</span><span class="ss">lang: :tr</span><span class="p">)</span>
</code></pre> Ruby master - Feature #19193 (Assigned): drop DOS TEXT mode supporthttps://redmine.ruby-lang.org/issues/191932022-12-09T16:38:20ZYO4 (Yoshinao Muramatsu)
<p>On Windows platform, <code>File.open(path, "r")</code> returns an object different from "rt" and "rb". I call that DOS TEXT mode here.</p>
<p>DOS TEXT mode does</p>
<ul>
<li>crlf conversion</li>
<li>0x1a treated EOF charactor on read</li>
</ul>
<p>and others (see Bug <a class="issue tracker-1 status-1 priority-4 priority-default" title="Bug: IO has third data mode, document is incomplete. (Open)" href="https://redmine.ruby-lang.org/issues/19192">#19192</a>).<br>
But DOS TEXT mode is almost unnecessary today and it seems to introduce lot of code complexities.</p>
<p>Now there is less need for dos text mode</p>
<ul>
<li>Microsoft's most apps works without CRLF newline.</li>
<li>Creating a crlf text file today should be explicit. (but that is default mode on windows now)</li>
<li>Interpreting EOF charactor can cause trouble.</li>
</ul>
<p>I think it's time to consider dropping DOS TEXT mode.<br>
What challenges are there and what preparation is needed?</p> Ruby master - Feature #19057 (Assigned): Hide implementation of `rb_io_t`.https://redmine.ruby-lang.org/issues/190572022-10-15T01:54:57Zioquatix (Samuel Williams)samuel@oriontransfer.net
<p>In order to make improvements to the IO implementation like <a href="https://bugs.ruby-lang.org/issues/18455" class="external">https://bugs.ruby-lang.org/issues/18455</a>, we need to add new fields to <code>struct rb_io_t</code>.</p>
<p>By the way, ending types in <code>_t</code> is not recommended by POSIX, so I'm also trying to rename the internal implementation to drop <code>_t</code> where possible during this conversion.</p>
<p>Anyway, we should try to hide the implementation of <code>struct rb_io</code>. Ideally, we don't expose any of it, but the problem is backwards compatibility.</p>
<p>So, in order to remain backwards compatibility, we should expose some fields of <code>struct rb_io</code>, the most commonly used one is <code>fd</code> and <code>mode</code>, but several others are commonly used.</p>
<p>There are many fields which should not be exposed because they are implementation details.</p>
<a name="Current-proposal"></a>
<h2 >Current proposal<a href="#Current-proposal" class="wiki-anchor">¶</a></h2>
<p>The current proposed change <a href="https://github.com/ruby/ruby/pull/6511" class="external">https://github.com/ruby/ruby/pull/6511</a> creates two structs:</p>
<pre><code class="c syntaxhl" data-language="c"><span class="c1">// include/ruby/io.h</span>
<span class="cp">#ifndef RB_IO_T
</span><span class="k">struct</span> <span class="n">rb_io</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">fd</span><span class="p">;</span>
<span class="c1">// ... public fields ...</span>
<span class="p">};</span>
<span class="cp">#else
</span><span class="k">struct</span> <span class="n">rb_io</span><span class="p">;</span>
<span class="cp">#endif
</span>
<span class="c1">// internal/io.h</span>
<span class="cp">#define RB_IO_T
</span><span class="k">struct</span> <span class="n">rb_io</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">fd</span><span class="p">;</span>
<span class="c1">// ... public fields ...</span>
<span class="c1">// ... private fields ...</span>
<span class="p">};</span>
</code></pre>
<p>However, we are not 100% confident this is safe according to the C specification. My experience is not sufficiently wide to say this is safe in practice, but it does look okay to both myself, and <a class="user active user-mention" href="https://redmine.ruby-lang.org/users/772">@Eregon (Benoit Daloze)</a> + <a class="user active user-mention" href="https://redmine.ruby-lang.org/users/73">@tenderlovemaking (Aaron Patterson)</a> have both given some kind of approval.</p>
<p>That being said, maybe it's not safe.</p>
<p>There are two alternatives:</p>
<a name="Hide-all-details"></a>
<h2 >Hide all details<a href="#Hide-all-details" class="wiki-anchor">¶</a></h2>
<p>We can make public <code>struct rb_io</code> completely invisible.</p>
<pre><code class="c syntaxhl" data-language="c"><span class="c1">// include/ruby/io.h</span>
<span class="cp">#define RB_IO_HIDDEN
</span><span class="k">struct</span> <span class="n">rb_io</span><span class="p">;</span>
<span class="kt">int</span> <span class="nf">rb_ioptr_descriptor</span><span class="p">(</span><span class="k">struct</span> <span class="n">rb_io</span> <span class="o">*</span><span class="n">ioptr</span><span class="p">);</span> <span class="c1">// accessor for previously visible state.</span>
<span class="c1">// internal/io.h</span>
<span class="k">struct</span> <span class="n">rb_io</span> <span class="p">{</span>
<span class="c1">// ... all fields ...</span>
<span class="p">};</span>
</code></pre>
<p>This would only be forwards compatible, and code would need to feature detect like this:</p>
<pre><code class="c syntaxhl" data-language="c"><span class="cp">#ifdef RB_IO_HIDDEN
#define RB_IOPTR_DESCRIPTOR rb_ioptr_descriptor
#else
#define RB_IOPTR_DESCRIPTOR(ioptr) rb_ioptr_descriptor(ioptr)
#endif
</span></code></pre>
<a name="Nested-public-interface"></a>
<h2 >Nested public interface<a href="#Nested-public-interface" class="wiki-anchor">¶</a></h2>
<p>Alternatively, we can nest the public fields into the private struct:</p>
<pre><code class="c syntaxhl" data-language="c"><span class="c1">// include/ruby/io.h</span>
<span class="k">struct</span> <span class="n">rb_io_public</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">fd</span><span class="p">;</span>
<span class="c1">// ... public fields ...</span>
<span class="p">};</span>
<span class="c1">// internal/io.h</span>
<span class="cp">#define RB_IO_T
</span><span class="k">struct</span> <span class="n">rb_io</span> <span class="p">{</span>
<span class="k">struct</span> <span class="n">rb_io_public</span> <span class="n">public</span><span class="p">;</span>
<span class="c1">// ... private fields ...</span>
<span class="p">};</span>
</code></pre>
<a name="Considerations"></a>
<h2 >Considerations<a href="#Considerations" class="wiki-anchor">¶</a></h2>
<p>I personally think the "Hide all details" implementation is the best, but it's also the lest compatible. This is also what we are ultimately aiming for, whether we decide to take an intermediate "compatibility step" is up to us.</p>
<p>I think "Nested public interface" is messy and introduces more complexity, but it might be slightly better defined than the "Current proposal" which might create undefined behaviour. That being said, all the tests are passing.</p> Ruby master - Bug #18940 (Assigned): Ruby Ractor fails with IOError when handling higher concurrencyhttps://redmine.ruby-lang.org/issues/189402022-07-26T18:33:12Zbrodock (Gabriel Mazetto)brodock@gmail.com
<p>Reproduction server:</p>
<pre><code>require 'socket'
# Set based on CPU count
CONCURRENCY = 8
server = TCPServer.new(8080)
workers = CONCURRENCY.times.map do
Ractor.new do
loop do
# receive TCPSocket
session = Ractor.recv
request = session.gets
puts request
session.print "HTTP/1.1 200\r\n"
session.print "Content-Type: text/html\r\n"
session.print "\r\n"
session.print "Hello world! Current time is #{Time.now}"
session.close
end
end
end
loop do
conn, _ = server.accept
# pass TCPSocket to one of the workers
workers.sample.send(conn, move: true)
end
</code></pre>
<p>run apache benchmark against code above:</p>
<pre><code>ab -n 20000 -c 20 http://localhost:8080/
</code></pre>
<p>or run using hey (<a href="https://github.com/rakyll/hey" class="external">https://github.com/rakyll/hey</a>):</p>
<pre><code>hey -n 20000 -c 20 http://localhost:8080/
</code></pre>
<p>you should see something like this on the benchmark tool side:</p>
<pre><code>Summary:
Total: 32.9538 secs
Slowest: 2.6317 secs
Fastest: 0.0002 secs
Average: 0.0331 secs
Requests/sec: 606.9098
Response time histogram:
0.000 [1] |
0.263 [16968] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
0.527 [1740] |■■■■
0.790 [0] |
1.053 [0] |
1.316 [0] |
1.579 [0] |
1.842 [0] |
2.105 [20] |
2.369 [0] |
2.632 [6] |
Latency distribution:
10% in 0.0008 secs
25% in 0.0010 secs
50% in 0.0012 secs
75% in 0.0016 secs
90% in 0.0075 secs
95% in 0.3101 secs
99% in 0.3175 secs
Details (average, fastest, slowest):
DNS+dialup: 0.0322 secs, 0.0002 secs, 2.6317 secs
DNS-lookup: 0.0006 secs, 0.0000 secs, 0.0127 secs
req write: 0.0001 secs, 0.0000 secs, 0.0095 secs
resp wait: 0.0007 secs, 0.0000 secs, 0.0140 secs
resp read: 0.0001 secs, 0.0000 secs, 0.0088 secs
Status code distribution:
[200] 18735 responses
Error distribution:
[1231] Get "http://localhost:8080/": dial tcp [::1]:8080: connect: connection refused
[16] Get "http://localhost:8080/": dial tcp [::1]:8080: connect: connection reset by peer
[1] Get "http://localhost:8080/": net/http: HTTP/1.x transport connection broken: unexpected EOF
[1] Get "http://localhost:8080/": read tcp 127.0.0.1:57078->127.0.0.1:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57054->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57058->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57059->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57062->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57067->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57068->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57069->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57070->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57071->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57072->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57075->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57076->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57087->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57088->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57089->[::1]:8080: read: connection reset by peer
[1] Get "http://localhost:8080/": read tcp [::1]:57090->[::1]:8080: read: connection reset by peer
</code></pre>
<p>and this on the ruby process:</p>
<pre><code>...
GET / HTTP/1.1
GET / HTTP/1.1
#<Thread:0x0000000100fbf6e8 run> terminated with exception (report_on_exception is true):
ractor.rb:21:in `write': GET / HTTP/1.1
uninitialized stream (IOError)
from ractor.rb:21:in `print'
from ractor.rb:21:in `block (3 levels) in <main>'
from ractor.rb:11:in `loop'
from ractor.rb:11:in `block (2 levels) in <main>'
GET / HTTP/1.1
GET / HTTP/1.1
</code></pre> Ruby master - Feature #18919 (Assigned): Ractor: can't share #Method objectshttps://redmine.ruby-lang.org/issues/189192022-07-15T22:07:09Zchucke (Tiago Cardoso)
<p>The following is not shareable:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">></span> <span class="n">meth</span> <span class="o">=</span> <span class="o">::</span><span class="no">Kernel</span><span class="p">.</span><span class="nf">method</span><span class="p">(</span><span class="ss">:BigDecimal</span><span class="p">)</span>
<span class="o">=></span> <span class="c1">#<Method: Kernel.BigDecimal(*)></span>
<span class="o"><</span><span class="n">internal</span><span class="ss">:ractor</span><span class="o">></span><span class="p">:</span><span class="mi">816</span><span class="ss">:in</span> <span class="sb">`make_shareable': can not make shareable object for #<Method: Kernel.BigDecimal(*)> (Ractor::Error)
</span></code></pre>
<p>I understand that procs have the issue of accessing outer-scope variables, but does the same apply to methods converted to procs?</p> Ruby master - Feature #18773 (Assigned): deconstruct to receive a rangehttps://redmine.ruby-lang.org/issues/187732022-05-11T17:13:54Zkddnewton (Kevin Newton)kddnewton@gmail.com
<p>Currently when you're pattern matching against a hash pattern, <code>deconstruct_keys</code> receives the keys that are being matched. This is really useful for computing expensive hashes.</p>
<p>However, when you're pattern matching against an array pattern, you don't receive any information. So if the array is expensive to compute (for instance loading an array of database records), you have no way to bail out. It would be useful to receive a range signifying how many records the pattern is specifying. It would be used like the following:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">ActiveRecord::Relation</span>
<span class="k">def</span> <span class="nf">deconstruct</span><span class="p">(</span><span class="n">range</span><span class="p">)</span>
<span class="p">(</span><span class="n">loaded?</span> <span class="o">||</span> <span class="n">range</span><span class="p">.</span><span class="nf">cover?</span><span class="p">(</span><span class="n">count</span><span class="p">))</span> <span class="p">?</span> <span class="n">records</span> <span class="p">:</span> <span class="kp">nil</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>It needs to be a range and not just a number to handle cases where <code>*</code> is used. You would use it like:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">case</span> <span class="no">Person</span><span class="p">.</span><span class="nf">all</span>
<span class="k">in</span> <span class="p">[]</span>
<span class="s2">"No records"</span>
<span class="k">in</span> <span class="p">[</span><span class="n">person</span><span class="p">]</span>
<span class="s2">"Only </span><span class="si">#{</span><span class="n">person</span><span class="p">.</span><span class="nf">name</span><span class="si">}</span><span class="s2">"</span>
<span class="k">else</span>
<span class="s2">"Multiple people"</span>
<span class="k">end</span>
</code></pre>
<p>In this way, you wouldn't have to load the whole thing into memory to check if it pattern matched. The patch is here: <a href="https://github.com/ruby/ruby/pull/5905" class="external">https://github.com/ruby/ruby/pull/5905</a>.</p> Ruby master - Bug #18677 (Assigned): BigDecimal#power (**) returns FloatDomainError when passing ...https://redmine.ruby-lang.org/issues/186772022-04-04T09:27:59Zdorianmariefr (Dorian Marié)
<p>Example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">></span> <span class="no">BigDecimal</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="o">**</span> <span class="no">BigDecimal</span><span class="p">(</span><span class="s2">"Infinity"</span><span class="p">)</span>
<span class="no">FloatDomainError</span><span class="p">:</span> <span class="no">Computation</span> <span class="n">results</span> <span class="k">in</span> <span class="s1">'Infinity'</span>
</code></pre>
<p>Maybe:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s2">"bigdecimal/util"</span>
<span class="k">class</span> <span class="nc">BigDecimal</span> <span class="o"><</span> <span class="no">Numeric</span>
<span class="k">def</span> <span class="nf">**</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="k">if</span> <span class="n">other</span><span class="p">.</span><span class="nf">infinite?</span> <span class="o">==</span> <span class="mi">1</span>
<span class="k">if</span> <span class="nb">self</span> <span class="o">></span> <span class="mi">1</span>
<span class="no">BigDecimal</span><span class="o">::</span><span class="no">INFINITY</span>
<span class="k">elsif</span> <span class="nb">self</span> <span class="o">==</span> <span class="mi">1</span>
<span class="nb">self</span>
<span class="k">elsif</span> <span class="nb">self</span> <span class="o">>=</span> <span class="mi">0</span>
<span class="no">BigDecimal</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">else</span>
<span class="n">power</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">else</span>
<span class="n">power</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">puts_and_eval</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
<span class="nb">puts</span> <span class="n">string</span>
<span class="nb">p</span> <span class="nb">eval</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">puts_and_eval</span> <span class="s2">"10 ** BigDecimal::INFINITY"</span>
<span class="n">puts_and_eval</span> <span class="s2">"1 ** BigDecimal::INFINITY"</span>
<span class="n">puts_and_eval</span> <span class="s2">"0.1 ** BigDecimal::INFINITY"</span>
<span class="n">puts_and_eval</span> <span class="s2">"0 ** BigDecimal::INFINITY"</span>
<span class="n">puts_and_eval</span> <span class="s2">"-1 ** BigDecimal::INFINITY"</span>
</code></pre>
<p>Seems like ruby is doing very different things from math though</p> Ruby master - Feature #18459 (Assigned): IRB autocomplete dropdown colour optionshttps://redmine.ruby-lang.org/issues/184592022-01-04T19:28:54Zjohansenjaa (Joseph Johansen)
<p>It would be great to be able to specify bg/fg colours for the new autocomplete dropdown in irb in ruby 3.1. This could help for accessibility purposes, or for anyone who just wants to make it look more personalised for their terminal 😎</p>
<p>Perhaps irbrc could do the trick?</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">IRB</span><span class="p">.</span><span class="nf">conf</span><span class="p">[</span><span class="ss">:AUTOCOMPLETE</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
<span class="no">BG_COLOR</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="no">FG_COLOR</span><span class="p">:</span> <span class="mi">15</span><span class="p">,</span>
<span class="p">}</span>
</code></pre> Ruby master - Feature #18450 (Assigned): Force break in prettyprinthttps://redmine.ruby-lang.org/issues/184502021-12-29T13:16:58Zfirasalkhalil (Firas al-Khalil)
<a name="Abstract"></a>
<h1 >Abstract<a href="#Abstract" class="wiki-anchor">¶</a></h1>
<p>Support force-breaking a group in the std's <a href="https://github.com/ruby/prettyprint" class="external">prettyprint</a></p>
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p>There is a need to forcibly break a group and transform breakables into<br>
newlines. The library doesn't provide this possibility, directly, through<br>
its public API.</p>
<a name="Proposal"></a>
<h1 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h1>
<p>Add a single convenience function to the library's public class <code>PrettyPrint</code></p>
<a name="Implementation"></a>
<h1 >Implementation<a href="#Implementation" class="wiki-anchor">¶</a></h1>
<p>An implementation was submitted to the project's github repository as a<br>
<a href="https://github.com/ruby/prettyprint/pull/2" class="external">pull request</a>.</p>
<p>Here's the patch:</p>
<pre><code>diff --git a/lib/prettyprint.rb b/lib/prettyprint.rb
index 188c2e6..1d675a7 100644
--- a/lib/prettyprint.rb
+++ b/lib/prettyprint.rb
@@ -236,6 +236,14 @@ class PrettyPrint
end
end
+ # This says "force a line break here".
+ #
+ # It will force the current group's "breakables" to break.
+ def break
+ breakable
+ current_group.break
+ end
+
# Groups line break hints added in the block. The line break hints are all
# to be used or not.
#
diff --git a/test/test_prettyprint.rb b/test/test_prettyprint.rb
index 27e7198..cf889d1 100644
--- a/test/test_prettyprint.rb
+++ b/test/test_prettyprint.rb
@@ -518,4 +518,31 @@ End
end
+
+class Break < Test::Unit::TestCase # :nodoc:
+ def format()
+ PrettyPrint.format(''.dup) {|q|
+ q.group {
+ q.text 'abc'
+ q.breakable
+ q.text 'def'
+ q.group {
+ q.break
+ q.text 'ghi'
+ }
+ q.breakable
+ q.text 'jkl'
+ }
+ }
+ end
+
+ def test_00_04
+ expected = <<'End'.chomp
+abc def
+ghi jkl
+End
+ assert_equal(expected, format())
+ end
+end
+
</code></pre>
<a name="Evaluation"></a>
<h1 >Evaluation<a href="#Evaluation" class="wiki-anchor">¶</a></h1>
<p>It's a simple implementation with no caveats.</p>
<a name="Discussion"></a>
<h1 >Discussion<a href="#Discussion" class="wiki-anchor">¶</a></h1>
<p>Even though it's a simple functionality, and the implementation is straightforward,<br>
getting to this point is not that obvious. This is why it might be helpful for other<br>
users who face such a need.</p>
<p>Indeed, an issue was <a href="https://github.com/ruby/prettyprint/issues/1" class="external">opened</a> not so long ago,<br>
and the proposed solution worked but not quite as expected. The provided implementation<br>
works as expected without tampering with the API's internals, and it's proven in production<br>
environment.</p>
<a name="Summary"></a>
<h1 >Summary<a href="#Summary" class="wiki-anchor">¶</a></h1>
<p>This is a feature request for the <code>prettyprint</code> library: adding support for <em>force breaking</em><br>
a group. An implementation is provided as both a patch and a PR on github.</p> Ruby master - Feature #18439 (Assigned): YJIT: Support Microsoft x86 calling conventionhttps://redmine.ruby-lang.org/issues/184392021-12-27T08:47:04Zusa (Usaku NAKAMURA)usa@garbagecollect.jp
<p>I heard that supporting YJIT for VC++ needs mmap from k0kubun-san, so I implemented tiny mmap emulation on Windows and committed it to master.<br>
And, I found we need more changes to actually enabled YJIT for VC++, at least:</p>
<ul>
<li>YJIT requires <code>OPT_DIRECT_THREADED_CODE</code> or <code>OPT_CALL_THREADED_CODE</code> in <code>rb_yjit_compile_iseq()</code>. Really?</li>
<li>Maybe ABI deffers between VC++ and YJIT's expectation.</li>
</ul>
<p>Can I get support to fix above?</p> Ruby master - Misc #18371 (Assigned): Release branches (release information in general)https://redmine.ruby-lang.org/issues/183712021-11-30T22:52:11Ztenderlovemaking (Aaron Patterson)tenderlove@ruby-lang.org
<p>Hi,</p>
<p>I was trying to learn about Ruby's release process. I noticed that we don't create a release branch until the final version is shipped. Is there a reason we don't create the release branch when the first preview is shipped? The reason I'm asking is because I'm worried about merging things to master after the first preview. Do we have any documentation on the release process? (I was searching and couldn't find much info, but maybe I didn't search correctly)</p>
<p>Thanks!</p> Ruby master - Bug #18337 (Assigned): Ruby allows zero-width characters in identifiershttps://redmine.ruby-lang.org/issues/183372021-11-15T00:14:21Zduerst (Martin Dürst)duerst@it.aoyama.ac.jp
<p>Ruby allows zero-width characters in identifiers, which can be shown with the following small test:</p>
<p>irb(main):001:0> script = "ab = 20; a\u200Bb = 30; puts ab;"<br>
=> "ab = 20; ab = 30; puts ab;"<br>
irb(main):002:0> eval(script)<br>
20<br>
=> nil</p>
<p>The first line creates the script. It contains a zero-width space (ZWSP), but that's not visible in most contexts (see next line). Looking at the script, one expects 30 as an output, but the output is 20 because there are two variables involved, one with a ZWSP and one without. I propose we fix this by disallowing such characters in identifiers. I'll give more details in a followup.</p> Ruby master - Bug #18119 (Assigned): Ractor crashes when instantiating classeshttps://redmine.ruby-lang.org/issues/181192021-08-19T13:23:40Zpeterzhu2118 (Peter Zhu)peter@peterzhu.ca
<p>The following script crashes with a segfault (tested on Ubuntu 20.04 and macOS 11.5.2):</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">workers</span> <span class="o">=</span> <span class="p">(</span><span class="mi">0</span><span class="o">...</span><span class="mi">8</span><span class="p">).</span><span class="nf">map</span> <span class="k">do</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="kp">loop</span> <span class="k">do</span>
<span class="mi">100</span><span class="p">.</span><span class="nf">times</span><span class="p">.</span><span class="nf">map</span> <span class="p">{</span> <span class="no">Class</span><span class="p">.</span><span class="nf">new</span> <span class="p">}</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">yield</span> <span class="kp">nil</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="mi">100</span><span class="p">.</span><span class="nf">times</span> <span class="p">{</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="o">*</span><span class="n">workers</span><span class="p">)</span> <span class="p">}</span>
</code></pre>
<p>Crash error:</p>
<pre><code><internal:ractor>:267: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues.
test.rb:4: [BUG] Segmentation fault at 0x0000000000000040
ruby 3.1.0dev (2021-08-19T08:44:48Z master 6963f8f743) [x86_64-linux]
-- Control frame information -----------------------------------------------
c:0010 p:---- s:0033 e:000032 CFUNC :new
c:0009 p:0011 s:0029 e:000028 BLOCK test.rb:4 [FINISH]
c:0008 p:---- s:0026 e:000025 IFUNC
c:0007 p:---- s:0023 e:000022 CFUNC :times
c:0006 p:---- s:0020 e:000019 CFUNC :each
c:0005 p:---- s:0017 e:000016 CFUNC :map
c:0004 p:0007 s:0013 e:000012 BLOCK test.rb:4 [FINISH]
c:0003 p:---- s:0010 e:000009 CFUNC :loop
c:0002 p:0004 s:0006 e:000005 BLOCK test.rb:3 [FINISH]
c:0001 p:---- s:0003 e:000002 (none) [FINISH]
-- Ruby level backtrace information ----------------------------------------
test.rb:3:in `block (2 levels) in <main>'
test.rb:3:in `loop'
test.rb:4:in `block (3 levels) in <main>'
test.rb:4:in `map'
test.rb:4:in `each'
test.rb:4:in `times'
test.rb:4:in `block (4 levels) in <main>'
test.rb:4:in `new'
-- Machine register context ------------------------------------------------
RIP: 0x0000562c1f9cd2cb RBP: 0x00007f6c3736d378 RSP: 0x00007f6c368285f0
RAX: 0x00007f6c1c00e208 RBX: 0x00007f6c3736d378 RCX: 0x0000562c20ed8330
RDX: 0x0000000000000000 RDI: 0x00007f6c100095c0 RSI: 0x0000000000000000
R8: 0x0000000000000007 R9: 0x0000562c20ed8120 R10: 0x0000000000000022
R11: 0x0000562c21180760 R12: 0x0000000000000000 R13: 0x00007f6c3736c000
R14: 0x0000000000000000 R15: 0x00007f6c3736d378 EFL: 0x0000000000010202
-- C level backtrace information -------------------------------------------
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_print_backtrace+0x11) [0x562c1f995e38] ../vm_dump.c:759
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_vm_bugreport) ../vm_dump.c:1041
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_bug_for_fatal_signal+0xec) [0x562c1f78a0bc] ../error.c:815
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(sigsegv+0x4d) [0x562c1f8ebcbd] ../signal.c:961
/lib/x86_64-linux-gnu/libpthread.so.0(__restore_rt+0x0) [0x7f6c3b2c63c0]
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_class_remove_from_super_subclasses+0x2b) [0x562c1f9cd2cb] ../class.c:99
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(obj_free+0x37a) [0x562c1f7ae95a] ../gc.c:3123
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(gc_plane_sweep+0x21) [0x562c1f7aef3d] ../gc.c:5322
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(gc_page_sweep) ../gc.c:5464
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(gc_sweep_step) ../gc.c:5630
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(gc_heap_prepare_minimum_pages+0x0) [0x562c1f7afd94] ../gc.c:5834
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(gc_sweep) ../gc.c:5837
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(gc_marks+0x1c0) [0x562c1f7b3df8] ../gc.c:8144
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(gc_start) ../gc.c:9013
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(heap_prepare+0x2f) [0x562c1f7b8b6f] ../gc.c:2131
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(heap_next_freepage) ../gc.c:2422
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(ractor_cache_slots) ../gc.c:2454
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(newobj_slowpath) ../gc.c:2495
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(newobj_slowpath_wb_protected) ../gc.c:2519
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(newobj_of0+0x5) [0x562c1f7b8ebd] ../gc.c:2562
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(newobj_of) ../gc.c:2572
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_wb_protected_newobj_of) ../gc.c:2596
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(class_alloc+0x5) [0x562c1f9cd49e] ../class.c:185
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_class_boot) ../class.c:230
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(class_call_alloc_func+0x5) [0x562c1f84e5d3] ../object.c:2075
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_class_alloc) ../object.c:2047
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_class_new_instance_pass_kw) ../object.c:2120
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_cfp_consistent_p+0x0) [0x562c1f96d6bc] ../vm_insnhelper.c:2989
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_call_cfunc_with_frame) ../vm_insnhelper.c:2991
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_sendish+0x303) [0x562c1f978393] ../vm_insnhelper.c:4562
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_exec_core+0xcd) [0x562c1f98316d] ../insns.def:775
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_vm_exec+0x197) [0x562c1f978fc7] ../vm.c:2164
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(collect_i+0x12) [0x562c1fa27bf2] ../enum.c:608
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_vm_pop_frame+0x0) [0x562c1f976ba8] ../vm_insnhelper.c:3795
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_yield_with_cfunc) ../vm_insnhelper.c:3796
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(invoke_block_from_c_bh+0x10) [0x562c1f97d0d3] ../vm.c:1359
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_yield) ../vm.c:1399
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_yield_0) ../vm_eval.c:1350
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_yield_1) ../vm_eval.c:1356
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(int_dotimes+0x5c) [0x562c1f83a49c] ../numeric.c:5014
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_cfp_consistent_p+0x0) [0x562c1f97dd4f] ../vm_eval.c:135
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_call0_cfunc_with_frame) ../vm_eval.c:137
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_call0_cfunc) ../vm_eval.c:149
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_call0_body) ../vm_eval.c:182
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_call0+0x1ea) [0x562c1f9812fa] ../vm_eval.c:72
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(iterate_method+0x3b) [0x562c1f981e9b] ../vm_eval.c:847
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_iterate0+0x101) [0x562c1f973001] ../vm_eval.c:1534
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_block_call_kw+0x76) [0x562c1f9731f6] ../vm_eval.c:1566
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(enumerator_block_call+0x59) [0x562c1fa358e9] ../enumerator.c:553
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_cfp_consistent_p+0x0) [0x562c1f97dd4f] ../vm_eval.c:135
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_call0_cfunc_with_frame) ../vm_eval.c:137
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_call0_cfunc) ../vm_eval.c:149
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_call0_body) ../vm_eval.c:182
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_call0+0x1ea) [0x562c1f9812fa] ../vm_eval.c:72
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(iterate_method+0x3b) [0x562c1f981e9b] ../vm_eval.c:847
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_iterate0+0x101) [0x562c1f973001] ../vm_eval.c:1534
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_lambda_call+0x75) [0x562c1f973295] ../vm_eval.c:1633
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(enum_collect+0x5b) [0x562c1fa29acb] ../enum.c:647
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_cfp_consistent_p+0x0) [0x562c1f96d6bc] ../vm_insnhelper.c:2989
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_call_cfunc_with_frame) ../vm_insnhelper.c:2991
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_sendish+0x303) [0x562c1f978393] ../vm_insnhelper.c:4562
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_exec_core+0x130) [0x562c1f9831d0] ../insns.def:756
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_vm_exec+0x197) [0x562c1f978fc7] ../vm.c:2164
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(invoke_block_from_c_bh+0x130) [0x562c1f97c85a] ../vm.c:1264
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_yield) ../vm.c:1399
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_yield_0) ../vm_eval.c:1350
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(loop_i) ../vm_eval.c:1449
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_vrescue2+0x114) [0x562c1f794694] ../eval.c:1023
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_rescue2+0x8e) [0x562c1f79490e] ../eval.c:1000
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_cfp_consistent_p+0x0) [0x562c1f96d6bc] ../vm_insnhelper.c:2989
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_call_cfunc_with_frame) ../vm_insnhelper.c:2991
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_sendish+0x303) [0x562c1f978393] ../vm_insnhelper.c:4562
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(vm_exec_core+0x130) [0x562c1f9831d0] ../insns.def:756
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_vm_exec+0x197) [0x562c1f978fc7] ../vm.c:2164
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(thread_do_start_proc+0x294) [0x562c1f930f24] ../thread.c:716
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(thread_do_start+0xc) [0x562c1f9336fc] ../thread.c:760
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(thread_start_func_2) ../thread.c:835
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(rb_native_cond_initialize+0x0) [0x562c1f933a09] ../thread_pthread.c:1051
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(register_cached_thread_and_wait) ../thread_pthread.c:1103
/home/spin/src/github.com/Shopify/ruby-master/install/bin/ruby(thread_start_func_1) ../thread_pthread.c:1058
/lib/x86_64-linux-gnu/libpthread.so.0(0x9609) [0x7f6c3b2ba609]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x43) [0x7f6c3b044293]
</code></pre> Ruby master - Bug #17998 (Assigned): ractor: process hanging (with ractors initialized, but not b...https://redmine.ruby-lang.org/issues/179982021-06-17T13:45:50Zchucke (Tiago Cardoso)
<p>I couldn't figure out how to reproduce this in a more contained way, so I'll share what I'm doing <a href="https://github.com/HoneyryderChuck/minitest/tree/issue-872" class="external">in this minitest branch</a>.</p>
<p>I'm trying to make minitest's parallel mode use ractors. If you look at the last commit of the branch, I'm:</p>
<ul>
<li>replacing the parallel executor with a ractor-based one;</li>
<li>I'm defining the ractor executor, where I have a ractor pipe that a pool will consume work from</li>
<li>I'm turning off parallel subset of tests (to reproduce the bug that I'll be describing).</li>
</ul>
<p>When I run <code>rake test</code> in my Mac (BigSur 11.4), the process hangs. I can see that the ractor threads are executing and running, but the test process doesn't respond to the INFO signal interrupt (which should tell me where the process is hanging). This seems like a bug in the VM, as no work is being sent to the parallel executor, i.e. all ractors should be sleeping (I've <code>puts</code>'d also the executor shutdown process, and it never reaches it).</p>
<p>If I replace the ractor-based executor back with the thread based executor, everything works as expected.</p> Ruby master - Bug #17882 (Assigned): bootstraptest/test_ractor.rb:224 segfaults on Cygwinhttps://redmine.ruby-lang.org/issues/178822021-05-22T16:03:35Zxtkoba (Tee KOBAYASHI)
<p>The attached test code is excerpted from <code>bootstraptest/test_ractor.rb:224</code>. This code causes a segmentation fault every time when run on <code>x86_64-cygwin</code>. There are at least 3 types of dying messages, as shown below.</p>
<p>I have no idea whether this is relevant to <a class="issue tracker-1 status-1 priority-4 priority-default" title="Bug: bootstraptest/test_ractor.rb:224 a random failing test with "The outgoing-port is already closed ... (Open)" href="https://redmine.ruby-lang.org/issues/17878">#17878</a>, which is an issue with the very same test code.</p>
<p>Type 1 (null pointer dereference):</p>
<pre><code>Thread 6 received signal SIGSEGV, Segmentation fault.
[Switching to Thread 5368]
VM_CF_BLOCK_HANDLER (cfp=0x0) at ../vm.c:115
115 const VALUE *ep = VM_CF_LEP(cfp);
(gdb) bt
#0 VM_CF_BLOCK_HANDLER (cfp=0x0) at ../vm.c:115
#1 0x00007ff6acedb495 in rb_vm_frame_block_handler (cfp=<optimized out>) at ../vm.c:128
#2 0x00007ff6acdd954e in pass_passed_block_handler (ec=0x80012bba0) at ../eval_intern.h:17
#3 rb_obj_call_init_kw (obj=obj@entry=123145240968920, argc=argc@entry=1, argv=argv@entry=0xffd0ca08, kw_splat=kw_splat@entry=0) at ../eval.c:1724
#4 0x00007ff6ace3efc2 in rb_class_new_instance (argc=argc@entry=1, argv=argv@entry=0xffd0ca08, klass=klass@entry=123145300575160) at ../object.c:2192
#5 0x00007ff6acdd1c30 in rb_exc_new_str (etype=etype@entry=123145300575160, str=<optimized out>) at ../error.c:1123
#6 0x00007ff6acdd29ad in rb_vraise (exc=123145300575160, fmt=<optimized out>, ap=<optimized out>) at ../error.c:2922
#7 0x00007ff6acdd29e5 in rb_raise (exc=0, fmt=0x0) at ../error.c:2930
#8 0x00007ff6acdf90e8 in rb_io_check_initialized (fptr=0x0) at ../io.c:767
#9 rb_io_check_initialized (fptr=<optimized out>) at ../io.c:764
#10 0x00007ff6acdf90fb in rb_io_check_closed (fptr=0x0) at ../io.c:774
#11 0x00007ff6ace011ec in prep_stdio (f=0x18023acb8 <reent_data+1336>, fmode=fmode@entry=1, klass=123145300573360, klass@entry=140697440105184, path=path@entry=0x7ff6acf158e0 <prelude_table+2944> "<STDIN>") at ../io.c:8239
#12 0x00007ff6ace0122f in rb_io_prep_stdin () at ../io.c:8255
#13 0x00007ff6acebc980 in thread_start_func_2 (th=0x0, th@entry=0x80011cbf0, stack_start=stack_start@entry=0xffd0ccf8) at ../thread.c:801
#14 0x00007ff6acebd032 in thread_start_func_1 (th_ptr=<optimized out>) at ../thread_pthread.c:1035
#15 0x000000018016d45f in pthread::thread_init_wrapper(void*) () from target:/usr/bin/cygwin1.dll
#16 0x00000001800ddbba in pthread_wrapper () from target:/usr/bin/cygwin1.dll
#17 0x0000000000000000 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
</code></pre>
<p>Type 2 (<code>rb_gc_mark()</code>: <code><address></code> is <code>T_ZOMBIE</code>):</p>
<pre><code>Thread 7 hit Breakpoint 1, rb_bug (fmt=0x7ff6acf1396a <stat_data_type+8138> "rb_gc_mark(): %p is T_ZOMBIE") at ../error.c:782
782 {
(gdb) bt
#0 rb_bug (fmt=0x7ff6acf1396a <stat_data_type+8138> "rb_gc_mark(): %p is T_ZOMBIE") at ../error.c:782
#1 0x00007ff6acdeae8f in gc_mark_children (objspace=objspace@entry=0x800053970, obj=obj@entry=123145240171400) at ../gc.c:6934
#2 0x00007ff6acdeafb0 in gc_mark_stacked_objects (objspace=0x800053970, incremental=incremental@entry=0, count=count@entry=0) at ../gc.c:6961
#3 0x00007ff6acded415 in gc_mark_stacked_objects_all (objspace=0x800053970) at ../gc.c:7001
#4 gc_marks_rest (objspace=objspace@entry=0x800053970) at ../gc.c:7972
#5 0x00007ff6acdec08c in gc_marks (full_mark=<optimized out>, objspace=0x800053970) at ../gc.c:8028
#6 gc_start (objspace=objspace@entry=0x800053970, reason=<optimized out>, reason@entry=256) at ../gc.c:8862
#7 0x00007ff6acdee522 in heap_prepare (heap=0x800053998, objspace=0x800053970) at ../gc.c:2153
#8 heap_next_freepage (heap=0x800053998, objspace=0x800053970) at ../gc.c:2444
#9 ractor_cache_slots (objspace=objspace@entry=0x800053970, cr=cr@entry=0x800135d60) at ../gc.c:2476
#10 0x00007ff6acdee61a in newobj_slowpath (alloc_size=<optimized out>, wb_protected=0, cr=0x800135d60, objspace=0x800053970, flags=11, klass=123145300573360) at ../gc.c:2517
#11 newobj_slowpath_wb_unprotected (klass=123145300573360, flags=11, objspace=0x800053970, cr=0x800135d60, alloc_size=<optimized out>) at ../gc.c:2547
#12 0x00007ff6acdee815 in newobj_of0 (klass=klass@entry=123145300573360, flags=flags@entry=11, wb_protected=wb_protected@entry=0, cr=<optimized out>, alloc_size=<optimized out>) at ../gc.c:2585
#13 0x00007ff6acdee86d in newobj_of (klass=klass@entry=123145300573360, flags=flags@entry=11, v1=v1@entry=0, v2=v2@entry=0, v3=v3@entry=0, wb_protected=wb_protected@entry=0, alloc_size=40) at ../gc.c:2594
#14 0x00007ff6acdeec23 in rb_wb_unprotected_newobj_of (klass=klass@entry=123145300573360, flags=flags@entry=11, size=40, size@entry=0) at ../gc.c:2610
#15 0x00007ff6acdf666c in io_alloc (klass=klass@entry=123145300573360) at ../io.c:1038
#16 0x00007ff6acdfbca9 in prep_io (fd=2, fmode=fmode@entry=65546, klass=klass@entry=123145300573360, path=path@entry=0x7ff6acf158f1 <prelude_table+2961> "<STDERR>") at ../io.c:8206
#17 0x00007ff6ace011d4 in prep_stdio (f=0x18023ae28 <reent_data+1704>, fmode=fmode@entry=10, klass=123145300573360, klass@entry=34361007456, path=path@entry=0x7ff6acf158f1 <prelude_table+2961> "<STDERR>") at ../io.c:8237
#18 0x00007ff6ace01295 in rb_io_prep_stderr () at ../io.c:8267
#19 0x00007ff6acebc9a6 in thread_start_func_2 (th=0x0, th@entry=0x800134550, stack_start=stack_start@entry=0xffa0ccf8) at ../thread.c:803
#20 0x00007ff6acebd032 in thread_start_func_1 (th_ptr=<optimized out>) at ../thread_pthread.c:1035
#21 0x000000018016d45f in pthread::thread_init_wrapper(void*) () from target:/usr/bin/cygwin1.dll
#22 0x00000001800ddbba in pthread_wrapper () from target:/usr/bin/cygwin1.dll
#23 0x0000000000000000 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
</code></pre>
<p>Type 3 (try to mark <code>T_NONE</code> object):</p>
<pre><code><OBJ_INFO:gc_mark_ptr@../gc.c:6580> 0x00006fffffe7fb70 [0 M ] T_NONE
------------------------------------------------------------------------
Thread 7 hit Breakpoint 1, rb_bug (fmt=fmt@entry=0x7ff6acf138a0 <stat_data_type+7936> "try to mark T_NONE object") at ../error.c:782
782 {
(gdb) bt
#0 rb_bug (fmt=fmt@entry=0x7ff6acf138a0 <stat_data_type+7936> "try to mark T_NONE object") at ../error.c:782
#1 0x00007ff6acdea5c9 in gc_mark_ptr (objspace=0x800053970, obj=123145300736880) at ../gc.c:6581
#2 0x00007ff6ace672ea in ractor_mark (ptr=0x800117240) at ../ractor.c:197
#3 0x00007ff6acdeafb0 in gc_mark_stacked_objects (objspace=objspace@entry=0x800053970, incremental=incremental@entry=1, count=count@entry=2147483647) at ../gc.c:6961
#4 0x00007ff6acded3f9 in gc_mark_stacked_objects_incremental (count=2147483647, objspace=0x800053970) at ../gc.c:6995
#5 gc_marks_rest (objspace=objspace@entry=0x800053970) at ../gc.c:7968
#6 0x00007ff6acdee4f1 in gc_marks_continue (heap=0x800053998, objspace=0x800053970) at ../gc.c:8012
#7 heap_prepare (heap=0x800053998, objspace=0x800053970) at ../gc.c:2148
#8 heap_next_freepage (heap=0x800053998, objspace=0x800053970) at ../gc.c:2444
#9 ractor_cache_slots (objspace=objspace@entry=0x800053970, cr=cr@entry=0x800129350) at ../gc.c:2476
#10 0x00007ff6acdee61a in newobj_slowpath (alloc_size=<optimized out>, wb_protected=0, cr=0x800129350, objspace=0x800053970, flags=11, klass=123145300573360) at ../gc.c:2517
#11 newobj_slowpath_wb_unprotected (klass=123145300573360, flags=11, objspace=0x800053970, cr=0x800129350, alloc_size=<optimized out>) at ../gc.c:2547
#12 0x00007ff6acdee815 in newobj_of0 (klass=klass@entry=123145300573360, flags=flags@entry=11, wb_protected=wb_protected@entry=0, cr=<optimized out>, alloc_size=<optimized out>) at ../gc.c:2585
#13 0x00007ff6acdee86d in newobj_of (klass=klass@entry=123145300573360, flags=flags@entry=11, v1=v1@entry=0, v2=v2@entry=0, v3=v3@entry=0, wb_protected=wb_protected@entry=0, alloc_size=40) at ../gc.c:2594
#14 0x00007ff6acdeec23 in rb_wb_unprotected_newobj_of (klass=klass@entry=123145300573360, flags=flags@entry=11, size=40, size@entry=0) at ../gc.c:2610
#15 0x00007ff6acdf666c in io_alloc (klass=klass@entry=123145300573360) at ../io.c:1038
#16 0x00007ff6acdfbca9 in prep_io (fd=0, fmode=fmode@entry=65537, klass=klass@entry=123145300573360, path=path@entry=0x7ff6acf158e0 <prelude_table+2944> "<STDIN>") at ../io.c:8206
#17 0x00007ff6ace011d4 in prep_stdio (f=0x18023acb8 <reent_data+1336>, fmode=fmode@entry=1, klass=123145300573360, klass@entry=140697440105184, path=path@entry=0x7ff6acf158e0 <prelude_table+2944> "<STDIN>") at ../io.c:8237
#18 0x00007ff6ace0122f in rb_io_prep_stdin () at ../io.c:8255
#19 0x00007ff6acebc980 in thread_start_func_2 (th=0x0, th@entry=0x80010dcb0, stack_start=stack_start@entry=0xffa0ccf8) at ../thread.c:801
#20 0x00007ff6acebd032 in thread_start_func_1 (th_ptr=<optimized out>) at ../thread_pthread.c:1035
#21 0x000000018016d45f in pthread::thread_init_wrapper(void*) () from target:/usr/bin/cygwin1.dll
#22 0x00000001800ddbba in pthread_wrapper () from target:/usr/bin/cygwin1.dll
#23 0x0000000000000000 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
</code></pre> Ruby master - Misc #17720 (Assigned): Cirrus CI to check non-x86_64 architecture cases by own mac...https://redmine.ruby-lang.org/issues/177202021-03-12T17:50:05Zjaruga (Jun Aruga)
<p>Hello!</p>
<p>This ticket is related to the tickets <a class="issue tracker-5 status-5 priority-4 priority-default closed" title="Misc: Enabling ARM 64/32-bit cases by Drone CI (Closed)" href="https://redmine.ruby-lang.org/issues/16234">#16234</a> <a class="issue tracker-5 status-5 priority-4 priority-default closed" title="Misc: Enabling IBM PowerPC/Z cases in Travis CI (Closed)" href="https://redmine.ruby-lang.org/issues/16360">#16360</a>. But I opened a new ticket because it is related to general non-x86_64 architecture CI cases.</p>
<p>I have a suggestion.</p>
<p>I see the <code>.travis.yml</code> was removed [1], and I also saw another open source project remove their <code>.travis.yml</code> because they could not get the credits to continue to run Travis [2]. I feel Travis is not really a possible option for every open source project for now.</p>
<p>While we have RubyCI, I think we still have a motivation to run a CI on non-x86_64 architectures at a pull-request timing. So, I investigated alternative CI. When checking GitHub Actions, I do not feel it will happen soon on GitHub Actions [3]. Then I found an interesting CI called "Cirrus CI", that might enable us to run CI on non-x86_64 architectures such as Mac M1 (arm) ppc64le and s390x beyond the cloud.</p>
<p>Cirrus CI has 2 types of features: "cloud" and "persistent workers". I see the Cirrus CI "cloud" feature has been used in the QEMU and podman projects [4][5]. It has a unique freeBSD host. However the remarkable feature for the Ruby project is the "persistent workers" [6] announced a few months ago, that is beyond the cloud. Because this feature enables us to use our own machines as a CI running host. You can see the examples running the CI with the machines such as Mac M1, iPhone, ppc64le and s390x on the page [6]. Maybe the used machine does not even have the global static IP. You can see other articles [7][8] too.</p>
<p>I can see some benefits to start Cirrus CI for the Ruby project.</p>
<ul>
<li>Possibly we can check Mac M1 (arm), ppc64le, s390x cases using machines used in RubyCI [9] and someone's machine such as @ReiOdaira's ppc64le/s390x machines at the pull-request timing.</li>
<li>When we face the CI issue, we can login to the machine and use the interactive debugging tool such as gdb to fix it.</li>
<li>The config file is YAML format and it has the matrix feature [10]. We are familiar with the YAML and matrix.</li>
</ul>
<p>What do you think? Positive or negative?<br>
Thank you.</p>
<p>[1] ruby removed .travis.yml: <a href="https://github.com/ruby/ruby/commit/6b978d542704a5614af5e9375c4b31b8d2618652" class="external">https://github.com/ruby/ruby/commit/6b978d542704a5614af5e9375c4b31b8d2618652</a><br>
[2] simde removed .travis.yml: <a href="https://github.com/simd-everywhere/simde/commit/17a27e7f2c3114225899f2ace14010cbbb2139b5" class="external">https://github.com/simd-everywhere/simde/commit/17a27e7f2c3114225899f2ace14010cbbb2139b5</a><br>
[3] GitHub Actions and ppc64le: <a href="https://github.community/t/self-hosted-runner-on-ppc64el-architecture/155337" class="external">https://github.community/t/self-hosted-runner-on-ppc64el-architecture/155337</a><br>
[4] QEMU: <a href="https://gitlab.com/qemu-project/qemu/-/blob/master/.cirrus.yml" class="external">https://gitlab.com/qemu-project/qemu/-/blob/master/.cirrus.yml</a><br>
[5] Podman: <a href="https://github.com/containers/podman/blob/master/.cirrus.yml" class="external">https://github.com/containers/podman/blob/master/.cirrus.yml</a><br>
[6] The issue ticket of Persistent Workers: <a href="https://github.com/cirruslabs/cirrus-ci-docs/issues/263#issuecomment-746900845" class="external">https://github.com/cirruslabs/cirrus-ci-docs/issues/263#issuecomment-746900845</a><br>
[7] Persistent Workers blog: <a href="https://medium.com/cirruslabs/announcing-public-beta-of-cirrus-ci-persistent-workers-7327a38004be" class="external">https://medium.com/cirruslabs/announcing-public-beta-of-cirrus-ci-persistent-workers-7327a38004be</a><br>
[8] Persistent Workers guide: <a href="https://cirrus-ci.org/guide/persistent-workers/" class="external">https://cirrus-ci.org/guide/persistent-workers/</a><br>
[9] RubyCI: <a href="https://rubyci.org/" class="external">https://rubyci.org/</a><br>
[10] Cirrus CI matrix feature: <a href="https://cirrus-ci.org/guide/writing-tasks/#matrix-modification" class="external">https://cirrus-ci.org/guide/writing-tasks/#matrix-modification</a></p> Ruby master - Feature #17684 (Assigned): Remove `--disable-gems` from release version of Rubyhttps://redmine.ruby-lang.org/issues/176842021-03-10T12:51:46Zhsbt (Hiroshi SHIBATA)hsbt@ruby-lang.org
<p>In my understand, <code>--disable-gems</code> is only debugging feature for ruby-core team.</p>
<p>But some users enabled its option in test environment for performance or etc. So, <code>--disable-gems</code> option is wrong usage for some users.</p>
<ul>
<li><a href="https://github.com/rubygems/bundler/issues/7487#issuecomment-569901549" class="external">https://github.com/rubygems/bundler/issues/7487#issuecomment-569901549</a></li>
<li><a href="https://github.com/rubygems/rubygems/pull/4440#issue-587031184" class="external">https://github.com/rubygems/rubygems/pull/4440#issue-587031184</a></li>
</ul>
<p>We should remove it from package version of ruby.</p> Ruby master - Feature #17679 (Assigned): Ractor incoming channel can consume unlimited resourceshttps://redmine.ruby-lang.org/issues/176792021-03-08T16:22:37Zmarcotc (Marco Costa)
<a name="Background"></a>
<h2 >Background<a href="#Background" class="wiki-anchor">¶</a></h2>
<p>In the <a href="https://github.com/DataDog/dd-trace-rb" class="external">ddtrace</a> gem, we want to move telemetry trace sending to a separate background Ractor. We’re concerned that if something goes wrong/gets delayed in this background Ractor, more and more data will accumulate in the send/receive channel until the Ruby VM crashes because it runs out of memory.</p>
<a name="How-to-reproduce-Ruby-version-amp-script"></a>
<h2 >How to reproduce (Ruby version & script)<a href="#How-to-reproduce-Ruby-version-amp-script" class="wiki-anchor">¶</a></h2>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">receiver_ractor</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="kp">loop</span> <span class="k">do</span>
<span class="n">message</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">receive</span>
<span class="nb">sleep</span> <span class="mi">1</span>
<span class="nb">puts</span> <span class="s2">"Processed </span><span class="si">#{</span><span class="n">message</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">counter</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="kp">true</span>
<span class="n">counter</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">receiver_ractor</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="n">counter</span><span class="p">)</span>
<span class="k">end</span>
</code></pre>
<a name="Expectation-and-result"></a>
<h2 >Expectation and result<a href="#Expectation-and-result" class="wiki-anchor">¶</a></h2>
<p>The result is that the Ruby VM crashes due to out of memory.<br>
We expect the Ruby VM to not crash.</p>
<a name="Suggested-solutions"></a>
<h2 >Suggested solutions<a href="#Suggested-solutions" class="wiki-anchor">¶</a></h2>
<p>Some ideas on how this can be improved:</p>
<ul>
<li>Having a way for the sender of data to detect if the receiver Ractor is falling behind (approximate size of queue, timestamp of last processed item, or similar?).</li>
<li>Having a way to limit the Ractor message receive buffer.</li>
</ul> Ruby master - Bug #17678 (Assigned): Ractors do not restart after forkhttps://redmine.ruby-lang.org/issues/176782021-03-08T16:19:45Zivoanjo (Ivo Anjo)ivo.anjo@datadoghq.com
<p>Hello there! I'm working at Datadog on the <code>ddtrace</code> gem -- <a href="https://github.com/DataDog/dd-trace-rb" class="external">https://github.com/DataDog/dd-trace-rb</a> and we're experimenting with using Ractors in our library but run into a few issues.</p>
<a name="Background"></a>
<h3 >Background<a href="#Background" class="wiki-anchor">¶</a></h3>
<p>When running a Ractor as a background process, the Ractor stops & does not restart when the application forks.</p>
<a name="How-to-reproduce-Ruby-version-amp-script"></a>
<h3 >How to reproduce (Ruby version & script)<a href="#How-to-reproduce-Ruby-version-amp-script" class="wiki-anchor">¶</a></h3>
<p><code>ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-linux]</code></p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">r2</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="kp">loop</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s2">"[</span><span class="si">#{</span><span class="no">Process</span><span class="p">.</span><span class="nf">pid</span><span class="si">}</span><span class="s2">] Ractor"</span><span class="p">;</span> <span class="nb">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">}</span>
<span class="k">end</span>
<span class="nb">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="nb">puts</span> <span class="s2">"[</span><span class="si">#{</span><span class="no">Process</span><span class="p">.</span><span class="nf">pid</span><span class="si">}</span><span class="s2">] Forking..."</span>
<span class="nb">fork</span> <span class="k">do</span>
<span class="nb">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="nb">puts</span> <span class="s2">"[</span><span class="si">#{</span><span class="no">Process</span><span class="p">.</span><span class="nf">pid</span><span class="si">}</span><span class="s2">] End fork."</span>
<span class="k">end</span>
<span class="kp">loop</span> <span class="k">do</span>
<span class="nb">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">end</span>
</code></pre>
<a name="Expectation-and-result"></a>
<h3 >Expectation and result<a href="#Expectation-and-result" class="wiki-anchor">¶</a></h3>
<p>The application prints “Ractor” each second in the main process, but not in the fork.</p>
<p>Expected the Ractor (defined as <code>r2</code>) to run in the fork.</p>
<pre><code>[29] Ractor
[29] Ractor
[29] Forking...
[29] Ractor
[29] Ractor
[29] Ractor
[29] Ractor
[29] Ractor
[32] End fork.
[29] Ractor
[29] Ractor
[29] Ractor
</code></pre>
<a name="Additional-notes"></a>
<h3 >Additional notes<a href="#Additional-notes" class="wiki-anchor">¶</a></h3>
<p>Threads do not restart across forks either, so it might not be unreasonable to expect consistent behavior. However, it’s possible to detect a dead Thread and recreate it after a fork (e.g. with <code>#alive?</code>, <code>#status</code>), but there’s no such mechanism for Ractors.</p>
<a name="Suggested-solutions"></a>
<h3 >Suggested solutions<a href="#Suggested-solutions" class="wiki-anchor">¶</a></h3>
<ol>
<li>Auto-restart Ractors after fork</li>
<li>Add additional methods to Ractors that allow users to check & manage the status of the Ractor, similar to Thread.</li>
</ol> Ruby master - Bug #17677 (Assigned): Ractor crashes fork when blockinghttps://redmine.ruby-lang.org/issues/176772021-03-08T16:19:22Zdelner (David Elner)
<a name="Background"></a>
<h2 >Background<a href="#Background" class="wiki-anchor">¶</a></h2>
<p>If you create a Ractor which blocks (e.g. <code>receive</code>), then fork the process, the fork will segfault upon completion.</p>
<a name="How-to-reproduce"></a>
<h2 >How to reproduce<a href="#How-to-reproduce" class="wiki-anchor">¶</a></h2>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">r2</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">receive</span>
<span class="k">end</span>
<span class="nb">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="nb">puts</span> <span class="s2">"Forking..."</span>
<span class="nb">fork</span> <span class="k">do</span>
<span class="nb">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="nb">puts</span> <span class="s2">"End fork."</span>
<span class="k">end</span>
<span class="kp">loop</span> <span class="k">do</span>
<span class="nb">puts</span> <span class="s2">"Main thread."</span>
<span class="nb">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">end</span>
</code></pre>
<a name="Expectation-and-result"></a>
<h2 >Expectation and result<a href="#Expectation-and-result" class="wiki-anchor">¶</a></h2>
<p>Application prints “Main thread” from main process every second, while fork prints “End fork.” then produces a segfault. Main process continues to run.</p>
<p>Expected fork to not raise a segfault.</p>
<pre><code><internal:ractor>:267: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues.
Forking...
Main thread.
Main thread.
End fork.
app/sandbox.rb:80: [BUG]: Device or resource busy (EBUSY)
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-linux]
-- Control frame information -----------------------------------------------
c:0003 p:---- s:0011 e:000010 CFUNC :fork
c:0002 p:0048 s:0007 E:001b48 EVAL app/sandbox.rb:80 [FINISH]
c:0001 p:0000 s:0003 E:002590 (none) [FINISH]
-- Ruby level backtrace information ----------------------------------------
app/sandbox.rb:80:in `<main>'
app/sandbox.rb:80:in `fork'
-- C level backtrace information -------------------------------------------
/usr/local/lib/libruby.so.3.0(rb_print_backtrace+0x11) [0x7f9848528cfb] vm_dump.c:758
/usr/local/lib/libruby.so.3.0(rb_vm_bugreport) vm_dump.c:998
/usr/local/lib/libruby.so.3.0(bug_report_end+0x0) [0x7f9848354808] error.c:763
/usr/local/lib/libruby.so.3.0(rb_bug_without_die) error.c:763
/usr/local/lib/libruby.so.3.0(die+0x0) [0x7f98482c6902] error.c:771
/usr/local/lib/libruby.so.3.0(rb_bug) error.c:773
/usr/local/lib/libruby.so.3.0(rb_bug_errno+0x3c) [0x7f9848354a1c] error.c:802
/usr/local/lib/libruby.so.3.0(rb_native_mutex_destroy+0x20) [0x7f98484ce380] thread_pthread.c:444
/usr/local/lib/libruby.so.3.0(rb_native_cond_initialize) (null):0
/usr/local/lib/libruby.so.3.0(ractor_free+0xd) [0x7f984844487d] ractor.c:229
/usr/local/lib/libruby.so.3.0(run_final+0xb) [0x7f9848371c66] gc.c:3670
/usr/local/lib/libruby.so.3.0(finalize_list) gc.c:3689
/usr/local/lib/libruby.so.3.0(rb_objspace_call_finalizer+0x33d) [0x7f984837cc5d] gc.c:3852
/usr/local/lib/libruby.so.3.0(rb_ec_cleanup+0x311) [0x7f984835f0b1] eval.c:184
/usr/local/lib/libruby.so.3.0(ruby_stop+0x9) [0x7f984835f339] eval.c:329
/usr/local/lib/libruby.so.3.0(rb_f_fork+0x1f) [0x7f98484402f8] process.c:4348
/usr/local/lib/libruby.so.3.0(rb_f_fork) process.c:4338
/usr/local/lib/libruby.so.3.0(vm_call_cfunc_with_frame+0x11b) [0x7f984850672b] vm_insnhelper.c:2898
/usr/local/lib/libruby.so.3.0(vm_call_method_each_type+0xf9) [0x7f98485192c9] vm_insnhelper.c:3388
/usr/local/lib/libruby.so.3.0(vm_call_method+0xb4) [0x7f9848519b24] vm_insnhelper.c:3506
/usr/local/lib/libruby.so.3.0(vm_sendish+0xb3) [0x7f984850a3d3] vm_insnhelper.c:4499
/usr/local/lib/libruby.so.3.0(vm_exec_core+0x140) [0x7f98485123e0] insns.def:770
/usr/local/lib/libruby.so.3.0(rb_vm_exec+0x176) [0x7f9848517b26] vm.c:2163
/usr/local/lib/libruby.so.3.0(rb_ec_exec_node+0xd9) [0x7f9848359719] eval.c:317
/usr/local/lib/libruby.so.3.0(ruby_run_node+0x55) [0x7f984835f395] eval.c:375
/usr/local/bin/ruby(main+0x5b) [0x565147e5410b] ./main.c:50
...
Main thread.
Main thread.
Main thread.
</code></pre>
<a name="Additional-notes"></a>
<h2 >Additional notes<a href="#Additional-notes" class="wiki-anchor">¶</a></h2>
<p>This does not happen if a blocking operation does not occur in the Ractor. E.g.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">r2</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="kp">loop</span> <span class="p">{</span> <span class="nb">puts</span> <span class="s2">"[</span><span class="si">#{</span><span class="no">Process</span><span class="p">.</span><span class="nf">pid</span><span class="si">}</span><span class="s2">] Ractor"</span><span class="p">;</span> <span class="nb">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<p>Segfault can also be prevented by invoking <code>close_incoming</code> prior to forking, although this raises another error internally.</p>
<p>It also does not crash on MacOS 10.15.7: ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin19].</p>
<a name="Suggested-solutions"></a>
<h2 >Suggested solutions<a href="#Suggested-solutions" class="wiki-anchor">¶</a></h2>
<p>(None)</p> Ruby master - Misc #17662 (Assigned): The heredoc pattern used in tests does not syntax highlight...https://redmine.ruby-lang.org/issues/176622021-02-27T16:22:19ZEregon (Benoit Daloze)
<p>This heredoc pattern</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="n">assert_ruby_status</span><span class="p">([],</span> <span class="s2">"</span><span class="si">#{</span><span class="o"><<-</span><span class="s2">"begin;"</span><span class="si">}</span><span class="se">\n</span><span class="si">#{</span><span class="o"><<-</span><span class="s1">'end;'</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="n">bug</span><span class="p">)</span>
<span class="k">begin</span><span class="p">;</span>
<span class="nb">exit</span><span class="p">(</span><span class="s2">"1"</span> <span class="o">==</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">start</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="o">&</span><span class="ss">:to_s</span><span class="p">).</span><span class="nf">value</span><span class="p">)</span>
<span class="k">end</span><span class="p">;</span>
</code></pre>
<p>completely breaks syntax highlighting in at least:</p>
<ul>
<li>GitHub: <a href="https://github.com/ruby/ruby/blob/36dde35e029c7a6607e6c674062ce6fc7a51c0bd/test/ruby/test_string.rb#L697" class="external">there</a> <a href="https://github.com/ruby/ruby/blob/36dde35e029c7a6607e6c674062ce6fc7a51c0bd/test/ruby/test_process.rb#L1545" class="external">are</a> <a href="https://github.com/ruby/ruby/blob/565aeb81e0886c835888a425e5d05ed99fb03238/test/ruby/test_thread.rb#L201" class="external">many</a> <a href="https://github.com/ruby/ruby/blob/36dde35e029c7a6607e6c674062ce6fc7a51c0bd/test/ruby/test_require.rb#L21" class="external">examples</a>
</li>
<li>Atom</li>
<li>RubyMine (and IntelliJ)</li>
<li>Likely many more editors based on TextMate grammars</li>
</ul>
<p>Could another pattern be used in tests inside the ruby/ruby repository (at least for <code>test/ruby</code>)?</p>
<p>Due to this issue, it is very annoying and inconvenient to look at/read/investigate many tests.</p>
<p>I think this pattern is also very complicated to understand (and using <code>;</code> is quite weird for this).<br>
I suggest to replace it with this obvious and simple pattern many people use:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="n">assert_ruby_status</span><span class="p">([],</span> <span class="o"><<~</span><span class="no">'RUBY'</span><span class="p">,</span> <span class="n">bug</span><span class="p">)</span><span class="sh">
exit("1" == Thread.start(1, &:to_s).value)
</span><span class="no"> RUBY</span>
</code></pre>
<p>This syntax highlights correctly in most (all?) editors, and as an added bonus the code inside the heredoc is also highlighted in some editors (due to the label being <code>RUBY</code>).</p> Ruby master - Feature #17638 (Assigned): Support backtracing with the libbacktrace libraryhttps://redmine.ruby-lang.org/issues/176382021-02-17T13:03:12Zxtkoba (Tee KOBAYASHI)
<p>It seems that Ruby's current <code>addr2line.c</code> has trouble with the DWARF 5 debugging format (Bug <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: DWARF5 support? (Closed)" href="https://redmine.ruby-lang.org/issues/17585">#17585</a>).</p>
<p>I propose that there be an option to use the libbacktrace library instead of <code>addr2line.c</code>.</p>
<p>A patch is attached for that. When using libbacktrace, the C level backtrace information looks as follows:</p>
<pre><code>-- C level backtrace information -------------------------------------------
0x7f0cc2b3b372 rb_vm_bugreport
/var/tmp/ruby.build/ruby-devel-x86_64/vm_dump.c:1047
0x7f0cc291e188 rb_bug_for_fatal_signal
/var/tmp/ruby.build/ruby-devel-x86_64/error.c:801
0x7f0cc2a8a137 sigsegv
/var/tmp/ruby.build/ruby-devel-x86_64/signal.c:960
0x7f0cc281a9bf ???
???:0
0x7f0cc247ddf7 ???
???:0
0x7f0cc2a8990d rb_f_kill
/var/tmp/ruby.build/ruby-devel-x86_64/signal.c:481
0x7f0cc2a2e684 proc_rb_f_kill
/var/tmp/ruby.build/ruby-devel-x86_64/process.c:8604
0x7f0cc2b0f2a4 ractor_safe_call_cfunc_m1
/var/tmp/ruby.build/ruby-devel-x86_64/vm_insnhelper.c:2734
0x7f0cc2b0fecb vm_call_cfunc_with_frame
/var/tmp/ruby.build/ruby-devel-x86_64/vm_insnhelper.c:2924
0x7f0cc2b10088 vm_call_cfunc
/var/tmp/ruby.build/ruby-devel-x86_64/vm_insnhelper.c:2945
0x7f0cc2b11b3b vm_call_method_each_type
/var/tmp/ruby.build/ruby-devel-x86_64/vm_insnhelper.c:3414
0x7f0cc2b11fde vm_call_method
/var/tmp/ruby.build/ruby-devel-x86_64/vm_insnhelper.c:3507
0x7f0cc2b121ca vm_call_general
/var/tmp/ruby.build/ruby-devel-x86_64/vm_insnhelper.c:3550
0x7f0cc2b144e7 vm_sendish
/var/tmp/ruby.build/ruby-devel-x86_64/vm_insnhelper.c:4525
0x7f0cc2b1b196 vm_exec_core
/var/tmp/ruby.build/ruby-devel-x86_64/insns.def:789
0x7f0cc2b308f5 rb_vm_exec
/var/tmp/ruby.build/ruby-devel-x86_64/vm.c:2162
0x7f0cc2b316e8 rb_iseq_eval_main
/var/tmp/ruby.build/ruby-devel-x86_64/vm.c:2419
0x7f0cc292778d rb_ec_exec_node
/var/tmp/ruby.build/ruby-devel-x86_64/eval.c:317
0x7f0cc29278d3 ruby_run_node
/var/tmp/ruby.build/ruby-devel-x86_64/eval.c:375
0x55ad53234234 main
./main.c:47
0x7f0cc2468e59 ???
???:0
0x55ad532340f9 ???
???:0
0xffffffffffffffff ???
???:0
</code></pre>
<p>The source code of libbacktrace is available from: <a href="https://github.com/ianlancetaylor/libbacktrace" class="external">https://github.com/ianlancetaylor/libbacktrace</a></p> Ruby master - Feature #17593 (Assigned): load_iseq_eval should override the ISeq pathhttps://redmine.ruby-lang.org/issues/175932021-01-29T18:05:42Zbyroot (Jean Boussier)byroot@ruby-lang.org
<p>Full context in <a href="https://github.com/Shopify/bootsnap/pull/343" class="external">https://github.com/Shopify/bootsnap/pull/343</a></p>
<p>Consider the following script</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">system</span><span class="p">(</span><span class="s1">'mkdir'</span><span class="p">,</span> <span class="s1">'-p'</span><span class="p">,</span> <span class="s1">'/tmp/build'</span><span class="p">,</span> <span class="s1">'/tmp/app'</span><span class="p">)</span>
<span class="no">File</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="s1">'/tmp/app/a.rb'</span><span class="p">,</span> <span class="s1">'p ["app/a", __FILE__, __dir__]'</span><span class="p">)</span>
<span class="no">File</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="s1">'/tmp/app/b.rb'</span><span class="p">,</span> <span class="s1">'p ["app/b", __FILE__, __dir__]'</span><span class="p">)</span>
<span class="no">File</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="s1">'/tmp/build/a.rb'</span><span class="p">,</span> <span class="s1">'p ["build/a", __FILE__, __dir__]; require_relative "b"'</span><span class="p">)</span>
<span class="vg">$iseq</span> <span class="o">=</span> <span class="no">RubyVM</span><span class="o">::</span><span class="no">InstructionSequence</span><span class="p">.</span><span class="nf">compile_file</span><span class="p">(</span><span class="s1">'/tmp/build/a.rb'</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">RubyVM::InstructionSequence</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">load_iseq</span><span class="p">(</span><span class="n">feature</span><span class="p">)</span>
<span class="k">if</span> <span class="n">feature</span> <span class="o">==</span> <span class="s2">"/tmp/app/a.rb"</span>
<span class="vg">$iseq</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="nb">require</span> <span class="s1">'/tmp/app/a.rb'</span>
</code></pre>
<p>Current behavior:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">[</span><span class="s2">"build/a"</span><span class="p">,</span> <span class="s2">"/tmp/build/a.rb"</span><span class="p">,</span> <span class="s2">"/private/tmp/build"</span><span class="p">]</span>
<span class="sr">/tmp/</span><span class="n">build</span><span class="o">/</span><span class="n">a</span><span class="p">.</span><span class="nf">rb</span><span class="p">:</span><span class="mi">1</span><span class="ss">:in</span> <span class="sb">`require_relative': cannot load such file -- /private/tmp/build/b (LoadError)
from /tmp/build/a.rb:1:in `</span><span class="o"><</span><span class="n">main</span><span class="o">></span><span class="s1">'
from <internal:/opt/rubies/3.0.0-pshopify2/lib/ruby/3.0.0/rubygems/core_ext/kernel_require.rb>:85:in `require'</span>
<span class="n">from</span> <span class="o"><</span><span class="n">internal</span><span class="ss">:/</span><span class="n">opt</span><span class="o">/</span><span class="n">rubies</span><span class="o">/</span><span class="mf">3.0</span><span class="o">.</span><span class="mi">0</span><span class="o">-</span><span class="n">pshopify2</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">ruby</span><span class="o">/</span><span class="mf">3.0</span><span class="o">.</span><span class="mi">0</span><span class="o">/</span><span class="n">rubygems</span><span class="o">/</span><span class="n">core_ext</span><span class="o">/</span><span class="n">kernel_require</span><span class="p">.</span><span class="nf">rb</span><span class="o">></span><span class="p">:</span><span class="mi">85</span><span class="ss">:in</span> <span class="sb">`require'
from /tmp/iseq_debug.rb:16:in `</span><span class="o"><</span><span class="n">main</span><span class="o">></span><span class="err">'</span>
</code></pre>
<p>Expected behavior</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">[</span><span class="s2">"build/a"</span><span class="p">,</span> <span class="s2">"/private/tmp/app/a.rb"</span><span class="p">,</span> <span class="s2">"/private/tmp/app"</span><span class="p">]</span>
<span class="p">[</span><span class="s2">"app/b"</span><span class="p">,</span> <span class="s2">"/private/tmp/app/b.rb"</span><span class="p">,</span> <span class="s2">"/private/tmp/app"</span><span class="p">]</span>
</code></pre>
<a name="Whats-going-on"></a>
<h3 >What's going on?<a href="#Whats-going-on" class="wiki-anchor">¶</a></h3>
<p><code>RubyVM::InstructionSequence</code> instances have a <code>pathobj</code> property that is recorded when the source is parsed, and when the ISeq is later evaled, the VM use that <code>path</code> as if you were loading a <code>.rb</code> file located at that path.</p>
<p>So if that source use constructs such as <code>require_relative</code>, <code>__FILE__</code>, <code>__dir__</code>, etc, they will all happen relative to where the source was located upon compilation, not relative to the source was upon evaluation.</p>
<a name="Why-is-it-a-problem"></a>
<h3 >Why is it a problem?<a href="#Why-is-it-a-problem" class="wiki-anchor">¶</a></h3>
<p>Some deployment strategies first build the application in one location, and then later move it elsewhere.</p>
<p>That's for instance the case on the Heroku platform. e.g. the deploy looks like</p>
<pre><code class="bash syntaxhl" data-language="bash">git clone <repo> /tmp/build_xxxx
<span class="nb">cd</span> /tmp/build_xxxx
rake assets:precompile ...
<span class="nb">mv</span> /tmp/build_xxxx /app
</code></pre>
<p>Because of this, all the ISeq cached by bootsnap when the code was in <code>/tmp/build_xxx</code> have to be invalidated as soon as the source is moved to <code>/app</code>, rendering ISeq caching ineffective, and even detrimental as it causes extra writes to disk without bringing any benefits.</p>
<a name="Solution"></a>
<h3 >Solution<a href="#Solution" class="wiki-anchor">¶</a></h3>
<p>I believe there are two changes that would be needed.</p>
<p>First I think that <code>load_iseq_eval</code> should set the <code>fname</code> as the top stack location. Either by copying the ISeq instance and change its <code>pathobj</code>, or by having a way to pass an optional path to <code>vm_set_top_stack</code> that would take precedence.</p>
<p>I experimented with <a href="https://github.com/Shopify/ruby/commit/192f5b477f924243e3f6621383e7a6ad02fbd63d" class="external">a quick hack that changes the ISeq <code>pathobj</code> in place</a>, and it does solve most of the problem.</p>
<p>However even with that quick hack another problem remain, the <code>__FILE__</code> still evaluate to the original source location. However <code>__dir__</code> works as expected, because it is a method that returns the top_stack location. I think <code>__FILE__</code> could be changed to be a method as well.</p> Ruby master - Bug #17578 (Assigned): mkmf experimental C++ Supporthttps://redmine.ruby-lang.org/issues/175782021-01-25T06:26:31Zcfis (Charlie Savage)
<p>I've been working on the Rice gem (<a href="https://github.com/jasonroelofs/rice" class="external">https://github.com/jasonroelofs/rice</a>) that wraps C++ code for use in Ruby.</p>
<p>I noticed that some c++ support was added to mkmf for Ruby 2.7. However, if I try to use it find a header it fails to work. For example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">find_header</span><span class="p">(</span><span class="s1">'rice.hpp'</span><span class="p">)</span>
</code></pre>
<p>The reason is the conftest uses gcc -E instead of g++ -E. To fix that requires overlading the cpp_command to support C++.</p>
<p>This the fix I have put in that works:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">MakeMakefile</span><span class="p">[</span><span class="s1">'C++'</span><span class="p">].</span><span class="nf">module_eval</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">cpp_command</span><span class="p">(</span><span class="n">outfile</span><span class="p">,</span> <span class="n">opt</span><span class="o">=</span><span class="s2">""</span><span class="p">)</span>
<span class="n">conf</span> <span class="o">=</span> <span class="n">cc_config</span><span class="p">(</span><span class="n">opt</span><span class="p">)</span>
<span class="k">if</span> <span class="vg">$universal</span> <span class="ow">and</span> <span class="p">(</span><span class="n">arch_flag</span> <span class="o">=</span> <span class="n">conf</span><span class="p">[</span><span class="s1">'ARCH_FLAG'</span><span class="p">])</span> <span class="ow">and</span> <span class="o">!</span><span class="n">arch_flag</span><span class="p">.</span><span class="nf">empty?</span>
<span class="n">conf</span><span class="p">[</span><span class="s1">'ARCH_FLAG'</span><span class="p">]</span> <span class="o">=</span> <span class="n">arch_flag</span><span class="p">.</span><span class="nf">gsub</span><span class="p">(</span><span class="sr">/(?:\G|\s)-arch\s+\S+/</span><span class="p">,</span> <span class="s1">''</span><span class="p">)</span>
<span class="k">end</span>
<span class="no">RbConfig</span><span class="o">::</span><span class="n">expand</span><span class="p">(</span><span class="s2">"$(CXX) -E </span><span class="si">#$INCFLAGS</span><span class="s2"> </span><span class="si">#$CPPFLAGS</span><span class="s2"> </span><span class="si">#$CFLAGS</span><span class="s2"> </span><span class="si">#{</span><span class="n">opt</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="no">CONFTEST_CXX</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">outfile</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span>
<span class="n">conf</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>The two changes over the default method are:</p>
<p>$(CC) -> $(CXX) -E<br>
#{CONFTEST_c} -> #{CONFTEST_cxx}</p>
<p>Could this change be merged in? I can provide a patch file if you would like.</p>
<p>Last, it wasn't obvious to me how to activate the C++ support in mkfm. I ended up doing this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="kp">include</span> <span class="no">MakeMakefile</span><span class="p">[</span><span class="s1">'C++'</span><span class="p">]</span>
</code></pre>
<p>Is that correct?</p> Ruby master - Bug #17516 (Assigned): forking in a ractor causes Ruby to crashhttps://redmine.ruby-lang.org/issues/175162021-01-06T10:56:50Zpkmuldoon (Phil Muldoon)
<p>I just want to point out, there's absolutely no reason to do this, but</p>
<p>r = Ractor.new do<br>
Process.fork()<br>
end</p>
<p>Will cause:</p>
<p><a href="internal:ractor" class="external">internal:ractor</a>:267: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues.<br>
[BUG] rb_thread_terminate_all: called by child thread (0x0000700004ddca40, 0x00007f981b567ee0)<br>
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin20]</p>
<p>-- Crash Report log information --------------------------------------------<br>
See Crash Report log file under the one of following:<br>
* ~/Library/Logs/DiagnosticReports<br>
* /Library/Logs/DiagnosticReports<br>
for more details.<br>
Don't forget to include the above Crash Report log file in bug reports.</p>
<p>-- Control frame information -----------------------------------------------<br>
c:0001 p:---- s:0003 e:000002 (none) [FINISH]</p>
<p>-- C level backtrace information -------------------------------------------<br>
=> #<Ractor:#3 (pry):5 terminated><br>
[4] pry(main)> /Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(rb_vm_bugreport+0x6cf) [0x103084d1f]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(rb_bug_without_die+0x206) [0x102e9e2b6]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(rb_bug+0x71) [0x103091e6b]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(rb_thread_terminate_all+0x329) [0x10301e5b9]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(rb_ractor_terminate_all+0xa3) [0x102f8acc3]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(rb_ec_cleanup+0x229) [0x102ea9299]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(ruby_stop+0x9) [0x102ea9509]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(thread_start_func_2+0x8ce) [0x103027fce]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(thread_start_func_1+0x10d) [0x10302753d]<br>
/usr/lib/system/libsystem_pthread.dylib(_pthread_start+0xe0) [0x7fff20382950]</p> Ruby master - Misc #17376 (Assigned): Reduce number of GitHub Actionshttps://redmine.ruby-lang.org/issues/173762020-12-08T09:45:17Znaruse (Yui NARUSE)naruse@airemix.jp
<p>At this time we have 127 checks for GitHub commits, but unfortunately GitHub UI only shows 100 checks.<br>
It sometimes makes we don't see a failed check.<br>
Could you reduce number of GitHub actions at least less than 100?</p> Ruby master - Feature #17363 (Assigned): Timeoutshttps://redmine.ruby-lang.org/issues/173632020-12-03T14:58:16Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>Builtin methods like <code>Queue.pop</code> and <code>Ractor.receive</code> have no timeout parameter.</p>
<p>We should either:</p>
<ul>
<li>provide such a parameter</li>
<li>and/or provide a <code>Timeout::wake</code> that raises an timeout error only if the block is currently sleeping.</li>
</ul>
<p>Details:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">q</span> <span class="o">=</span> <span class="no">Queue</span><span class="p">.</span><span class="nf">new</span>
<span class="c1"># ...</span>
<span class="n">elem</span> <span class="o">=</span> <span class="no">Timeout</span><span class="o">::</span><span class="n">timeout</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span> <span class="p">{</span> <span class="n">q</span><span class="p">.</span><span class="nf">pop</span> <span class="p">}</span> <span class="c1"># => It is possible that an element is retreived from the queue but never stored in `elem`</span>
<span class="n">elem</span> <span class="o">=</span> <span class="no">Timeout</span><span class="o">::</span><span class="n">wake</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span> <span class="p">{</span> <span class="n">q</span><span class="p">.</span><span class="nf">pop</span> <span class="p">}</span> <span class="c1"># => Guaranteed that either element is retrieved from the queue or an exception is raised, never both</span>
<span class="no">Timeout</span><span class="o">::</span><span class="n">wake</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span> <span class="p">{</span> <span class="kp">loop</span> <span class="p">{}</span> <span class="p">}</span> <span class="c1"># => infinite loop</span>
<span class="c1"># and/or</span>
<span class="n">elem</span> <span class="o">=</span> <span class="n">q</span><span class="p">.</span><span class="nf">pop</span><span class="p">(</span><span class="ss">timeout: </span><span class="mi">42</span><span class="p">)</span>
</code></pre>
<p>Currently, the only reliable way to have a Queue that accepts a timeout is to re-implement it from scratch. This post describe how involved that can be: <a href="https://spin.atomicobject.com/2017/06/28/queue-pop-with-timeout-fixed/" class="external">https://spin.atomicobject.com/2017/06/28/queue-pop-with-timeout-fixed/</a></p> Ruby master - Feature #17355 (Assigned): Using same set of names in or-patterns (pattern matching...https://redmine.ruby-lang.org/issues/173552020-11-29T19:41:28Zdecuplet (Nikita Shilnikov)fg@flashgordon.ru
<p>Given pattern matching is officially supported in Ruby 3, I have an idea about making it more flexible.</p>
<p>Currently, this piece of code produces a syntax error</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">case</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="k">in</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="n">a</span><span class="p">]</span> <span class="o">|</span> <span class="p">[</span><span class="n">a</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span> <span class="o">=></span> <span class="n">a</span> <span class="k">then</span> <span class="n">a</span>
<span class="k">end</span> <span class="c1"># duplicated variable name</span>
</code></pre>
<p>Duplications don't seem to be a problem here, semantically-wise. We just need to check if all patterns have the same set of names. It's supported in OCaml (also here's an RFC in Rust <a href="https://github.com/rust-lang/rust/issues/54883" class="external">https://github.com/rust-lang/rust/issues/54883</a>) so I think it can work in Ruby too.</p>
<p>I've been using pattern matching in Ruby since day 1 and it worked great so far. Since I use OCaml daily too I miss this feature every once in a while :)<br>
A more practical example: imagine you have code like this</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">user_email</span><span class="p">(</span><span class="n">user</span><span class="p">)</span>
<span class="k">case</span> <span class="n">user</span>
<span class="k">in</span> <span class="no">User</span><span class="p">(</span><span class="n">email</span><span class="p">:)</span> <span class="k">then</span> <span class="n">email</span>
<span class="k">in</span> <span class="no">Admin</span><span class="p">(</span><span class="n">email</span><span class="p">:)</span> <span class="k">then</span> <span class="n">email</span>
<span class="k">in</span> <span class="no">Moderator</span><span class="p">(</span><span class="n">email</span><span class="p">:)</span> <span class="k">then</span> <span class="n">email</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>Clearly, it could be simplified if or-patterns were supported:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">user_email</span><span class="p">(</span><span class="n">user</span><span class="p">)</span>
<span class="k">case</span> <span class="n">user</span>
<span class="k">in</span> <span class="no">User</span><span class="p">(</span><span class="n">email</span><span class="p">:)</span> <span class="o">|</span> <span class="no">Admin</span><span class="p">(</span><span class="n">email</span><span class="p">:)</span> <span class="o">|</span> <span class="no">Moderator</span><span class="p">(</span><span class="n">email</span><span class="p">:)</span> <span class="k">then</span> <span class="n">email</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>I'd like to know @ktsj's thoughts on this.</p> Ruby master - Feature #17339 (Assigned): Semantic grouping with BigDecimal#to_shttps://redmine.ruby-lang.org/issues/173392020-11-21T07:05:31Zchumaltd (Takahiro Chuma)
<a name="Abstract"></a>
<h1 >Abstract<a href="#Abstract" class="wiki-anchor">¶</a></h1>
<p>Thousands, millions, ... should be expressible with <code>BigDecimal#to_s</code>.</p>
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p><code>BigDecimal('1234567').to_s('3F')</code> returns "123 456 7.0".</p>
<a name="Proposal"></a>
<h1 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h1>
<ul>
<li>Have an option with which <code>BigDecimal('1234567').to_s('3F')</code> returns "<em>1 234 567</em>.0".</li>
<li>With decimal, <code>BigDecimal('1234567.8901234').to_s('3F')</code> should return "1 234 567.890 123 4".</li>
<li>Default behavior should be the above in long term.</li>
<li>And/Or, it would be nice to have a pretty method name. I think #to_s('3F') has universal use cases like money calculation.</li>
</ul>
<a name="Discussion"></a>
<h1 >Discussion<a href="#Discussion" class="wiki-anchor">¶</a></h1>
<ul>
<li>International System of Units aka SI defines 3-digit-grouping on long numeric sequence.<br>
<a href="https://www1.bipm.org/jsp/en/ViewCGPMResolution.jsp?CGPM=22&RES=10" class="external">https://www1.bipm.org/jsp/en/ViewCGPMResolution.jsp?CGPM=22&RES=10</a>
</li>
<li>Original discussion in 1948 shows some example of 3-digit-grouping.<br>
<a href="https://www1.bipm.org/utils/common/pdf/CGPM/CGPM9.pdf#page=117" class="external">https://www1.bipm.org/utils/common/pdf/CGPM/CGPM9.pdf#page=117</a>
</li>
</ul>
<a name="Summary"></a>
<h1 >Summary<a href="#Summary" class="wiki-anchor">¶</a></h1>
<p>We want to have a natural format.</p> Ruby master - Feature #17297 (Assigned): Feature: Introduce Pathname.mktmpdirhttps://redmine.ruby-lang.org/issues/172972020-10-30T15:09:41Zschneems (Richard Schneeman)
<p>When I want to create a tmpdir I often want to manipulate it as a pathname. By introducing Pathname.mktmpdir I can get this behavior.</p>
<p>Currently I must:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Dir</span><span class="p">.</span><span class="nf">mktmpdir</span> <span class="k">do</span> <span class="o">|</span><span class="n">dir</span><span class="o">|</span>
<span class="n">dir</span> <span class="o">=</span> <span class="no">Pathname</span><span class="p">(</span><span class="n">dir</span><span class="p">)</span>
<span class="c1"># ... code</span>
<span class="k">end</span>
</code></pre>
<p>I would like to be able to instead:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Pathname</span><span class="p">.</span><span class="nf">mktmpdir</span> <span class="k">do</span> <span class="o">|</span><span class="n">dir</span><span class="o">|</span>
<span class="c1"># ... code</span>
<span class="k">end</span>
</code></pre>
<p>Diff:</p>
<pre><code>$ git diff master
diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb
index e6fb90277d..ec32e7d611 100644
--- a/ext/pathname/lib/pathname.rb
+++ b/ext/pathname/lib/pathname.rb
@@ -597,3 +597,20 @@ def rmtree
end
end
+class Pathname # * tmpdir *
+ # Creates a tmp directory and wraps the returned path in a Pathname object.
+ #
+ # See Dir.mktmpdir
+ def self.mktmpdir
+ require 'tmpdir' unless defined?(Dir.mktmpdir)
+ if block_given?
+ Dir.mktmpdir do |dir|
+ dir = self.new(dir)
+ yield dir
+ end
+ else
+ self.new(Dir.mktmpdir)
+ end
+ end
+end
+
diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb
index 43cef4849f..8edcccf666 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -1272,6 +1272,14 @@ def test_s_glob_3args
}
end
+ def test_mktmpdir
+ Pathname.mktmpdir do |dir|
+ assert_equal Pathname(dir), dir
+ assert dir.directory?
+ assert dir.exist?
+ end
+ end
+
def test_s_getwd
wd = Pathname.getwd
assert_kind_of(Pathname, wd)
</code></pre>
<p>Github link: <a href="https://github.com/ruby/ruby/pull/3709" class="external">https://github.com/ruby/ruby/pull/3709</a></p> Ruby master - Feature #17296 (Assigned): Feature: Pathname#chmod use FileUtils.chmod instead of Filehttps://redmine.ruby-lang.org/issues/172962020-10-30T15:08:09Zschneems (Richard Schneeman)
<p>The <code>FileUtils.chmod</code> provides the same numerical interface as <code>File.chmod</code> and it also includes a "symbolic mode" interface. With this patch you'll be able to run this code:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Pathname</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"bin/compile"</span><span class="p">).</span><span class="nf">chmod</span><span class="p">(</span><span class="s2">"+x"</span><span class="p">)</span>
</code></pre>
<p>I believe that this is backwards compatible with the existing implementation and all changes are an extension. The only difference between File.chmod and FileUtils.chmod I could find is they have different return values and the previous implementation of <code>Pathname#chmod</code> returned the result of the <code>File.chmod</code> call. From the docs <code>File.chmod</code> returns the number of files modified, since we're only ever able to pass in a maximum of one file through this interface, the return value will always be a <code>1</code> or an exception if the file does not exist.</p>
<p>I checked and the exceptions when the file does not exist match:</p>
<pre><code>irb(main):004:0> File.chmod(0444, "doesnotexist.txt")
Traceback (most recent call last):
6: from /Users/rschneeman/.rubies/ruby-2.7.2/bin/irb:23:in `<main>'
5: from /Users/rschneeman/.rubies/ruby-2.7.2/bin/irb:23:in `load'
4: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'
3: from (irb):3
2: from (irb):4:in `rescue in irb_binding'
1: from (irb):4:in `chmod'
Errno::ENOENT (No such file or directory @ apply2files - doesnotexist.txt)
irb(main):005:0> FileUtils.chmod(0444, "doesnotexist.txt")
Traceback (most recent call last):
10: from /Users/rschneeman/.rubies/ruby-2.7.2/bin/irb:23:in `<main>'
9: from /Users/rschneeman/.rubies/ruby-2.7.2/bin/irb:23:in `load'
8: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'
7: from (irb):4
6: from (irb):5:in `rescue in irb_binding'
5: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/2.7.0/fileutils.rb:1016:in `chmod'
4: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/2.7.0/fileutils.rb:1016:in `each'
3: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/2.7.0/fileutils.rb:1017:in `block in chmod'
2: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/2.7.0/fileutils.rb:1346:in `chmod'
1: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/2.7.0/fileutils.rb:1346:in `chmod'
Errno::ENOENT (No such file or directory @ apply2files - doesnotexist.txt)
</code></pre>
<p>If you're open to changing the interface of the return value my preference would be to return <code>self</code> from this method so that it can be chained. Otherwise this current patch is a smaller change.</p>
<p>Diff:</p>
<pre><code>$ git diff master
diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb
index e6fb90277d..cb6e32d9ac 100644
--- a/ext/pathname/lib/pathname.rb
+++ b/ext/pathname/lib/pathname.rb
@@ -585,6 +585,15 @@ def mkpath
nil
end
+ # Changes file permissions.
+ #
+ # See FileUtils.chmod
+ def chmod(mode)
+ require 'fileutils'
+ FileUtils.chmod(mode, self)
+ return 1
+ end
+
# Recursively deletes a directory, including all directories beneath it.
#
# See FileUtils.rm_r
diff --git a/ext/pathname/pathname.c b/ext/pathname/pathname.c
index f71cec1b25..6778d4f102 100644
--- a/ext/pathname/pathname.c
+++ b/ext/pathname/pathname.c
@@ -12,7 +12,6 @@ static ID id_binwrite;
static ID id_birthtime;
static ID id_blockdev_p;
static ID id_chardev_p;
-static ID id_chmod;
static ID id_chown;
static ID id_ctime;
static ID id_directory_p;
@@ -552,20 +551,6 @@ path_mtime(VALUE self)
return rb_funcall(rb_cFile, id_mtime, 1, get_strpath(self));
}
-/*
- * call-seq:
- * pathname.chmod(mode_int) -> integer
- *
- * Changes file permissions.
- *
- * See File.chmod.
- */
-static VALUE
-path_chmod(VALUE self, VALUE mode)
-{
- return rb_funcall(rb_cFile, id_chmod, 2, mode, get_strpath(self));
-}
-
/*
* call-seq:
* pathname.lchmod(mode_int) -> integer
@@ -1448,7 +1433,6 @@ path_f_pathname(VALUE self, VALUE str)
* - #birthtime
* - #ctime
* - #mtime
- * - #chmod(mode)
* - #lchmod(mode)
* - #chown(owner, group)
* - #lchown(owner, group)
@@ -1495,6 +1479,7 @@ path_f_pathname(VALUE self, VALUE str)
* === Utilities
*
* These methods are a mixture of Find, FileUtils, and others:
+ * - #chmod(mode)
* - #find(&block)
* - #mkpath
* - #rmtree
@@ -1542,7 +1527,6 @@ Init_pathname(void)
rb_define_method(rb_cPathname, "birthtime", path_birthtime, 0);
rb_define_method(rb_cPathname, "ctime", path_ctime, 0);
rb_define_method(rb_cPathname, "mtime", path_mtime, 0);
- rb_define_method(rb_cPathname, "chmod", path_chmod, 1);
rb_define_method(rb_cPathname, "lchmod", path_lchmod, 1);
rb_define_method(rb_cPathname, "chown", path_chown, 2);
rb_define_method(rb_cPathname, "lchown", path_lchown, 2);
@@ -1618,7 +1602,6 @@ InitVM_pathname(void)
id_birthtime = rb_intern("birthtime");
id_blockdev_p = rb_intern("blockdev?");
id_chardev_p = rb_intern("chardev?");
- id_chmod = rb_intern("chmod");
id_chown = rb_intern("chown");
id_ctime = rb_intern("ctime");
id_directory_p = rb_intern("directory?");
diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb
index 43cef4849f..5673691231 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -823,6 +823,11 @@ def test_chmod
path.chmod(0444)
assert_equal(0444, path.stat.mode & 0777)
path.chmod(old)
+
+ skip "Windows has different symbolic mode" if /mswin|mingw/ =~ RUBY_PLATFORM
+ path.chmod("u=wrx,g=rx,o=x")
+ assert_equal(0751, path.stat.mode & 0777)
+ path.chmod(old)
}
end
</code></pre>
<p>Github link: <a href="https://github.com/ruby/ruby/pull/3708" class="external">https://github.com/ruby/ruby/pull/3708</a></p> Ruby master - Feature #17295 (Assigned): Feature: Create a directory and file with Pathname#touchhttps://redmine.ruby-lang.org/issues/172952020-10-30T15:06:39Zschneems (Richard Schneeman)
<p>Right now if a developer wants to create a file and is not sure if the path exists yet or not they must:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Pathname</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"/a/b/c/d.txt"</span><span class="p">).</span><span class="nf">tap</span> <span class="p">{</span><span class="o">|</span><span class="nb">p</span><span class="o">|</span> <span class="nb">p</span><span class="p">.</span><span class="nf">dirname</span><span class="p">.</span><span class="nf">mkpath</span><span class="p">;</span> <span class="no">FileUtils</span><span class="p">.</span><span class="nf">touch</span><span class="p">(</span><span class="nb">p</span><span class="p">)}</span>
</code></pre>
<p>After this patch a developer can instead call:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Pathname</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"/a/b/c/d.txt"</span><span class="p">).</span><span class="nf">touch</span>
</code></pre>
<p>An alternative name for this behavior could be <code>mkfile</code> but I think it is confusing to have a <code>mkfile</code> and a <code>mkpath</code> where one creates a directory and one creates a file.</p>
<p>Diff:</p>
<pre><code>$ git diff master
diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb
index e6fb90277d..2ed02a6633 100644
--- a/ext/pathname/lib/pathname.rb
+++ b/ext/pathname/lib/pathname.rb
@@ -585,6 +585,27 @@ def mkpath
nil
end
+ # Creates a file and the full path to the file including any intermediate directories that don't yet
+ # exist.
+ #
+ # Example:
+ #
+ # Dir.exist?("/a/b/c") # => false
+ #
+ # p = Pathname.new("/a/b/c/d.txt")
+ # p.file? => false
+ # p.touch
+ # p.file? => true
+ #
+ # Dir.exist?("/a/b/c") # => true
+ def touch
+ require 'fileutils'
+ dirname.mkpath
+
+ FileUtils.touch(self)
+ self
+ end
+
# Recursively deletes a directory, including all directories beneath it.
#
# See FileUtils.rm_r
diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb
index 43cef4849f..3c518cc3da 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -1394,6 +1394,14 @@ def test_mkpath
}
end
+ def test_touch
+ with_tmpchdir('rubytest-pathname') {|dir|
+ Pathname("a/b/c/d.txt").touch
+ assert_file.directory?("a/b/c")
+ assert_file.file?("a/b/c/d.txt")
+ }
+ end
+
def test_rmtree
with_tmpchdir('rubytest-pathname') {|dir|
Pathname("a/b/c/d").mkpath
</code></pre>
<p>Github link: <a href="https://github.com/ruby/ruby/pull/3706" class="external">https://github.com/ruby/ruby/pull/3706</a></p> Ruby master - Feature #17294 (Assigned): Feature: Allow method chaining with Pathname#mkpath Path...https://redmine.ruby-lang.org/issues/172942020-10-30T15:04:06Zschneems (Richard Schneeman)
<p>Currently in my code when I want to create a pathname object and create a path at the same time I must use tap</p>
<pre><code>path = Pathname.new("/tmp/new").tap(&:mkpath)
</code></pre>
<p>I think it would be cleaner to be able to chain on the results of these methods instead:</p>
<pre><code>path = Pathname.new("/tmp/new").mkpath
</code></pre>
<p>This is a change in return value but after research on github I do not believe many (if any) are relying on the current behavior to return nil <a href="https://github.com/search?l=&p=1&q=.mkpath+language%3ARuby&ref=advsearch&type=Code" class="external">https://github.com/search?l=&p=1&q=.mkpath+language%3ARuby&ref=advsearch&type=Code</a>.</p>
<p>Here is my diff:</p>
<pre><code>$ git diff master schneems/return-self-pathname
diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb
index e6fb90277d..f1eb1e00ae 100644
--- a/ext/pathname/lib/pathname.rb
+++ b/ext/pathname/lib/pathname.rb
@@ -582,7 +582,7 @@ class Pathname # * FileUtils *
def mkpath
require 'fileutils'
FileUtils.mkpath(@path)
- nil
+ self
end
# Recursively deletes a directory, including all directories beneath it.
@@ -593,7 +593,7 @@ def rmtree
# File::Path provides "mkpath" and "rmtree".
require 'fileutils'
FileUtils.rm_r(@path)
- nil
+ self
end
end
diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb
index 43cef4849f..149fe15c3a 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -1389,7 +1389,8 @@ def test_find
def test_mkpath
with_tmpchdir('rubytest-pathname') {|dir|
- Pathname("a/b/c/d").mkpath
+ path = Pathname("a/b/c/d")
+ assert_equal(path, path.mkpath)
assert_file.directory?("a/b/c/d")
}
end
@@ -1398,7 +1399,8 @@ def test_rmtree
with_tmpchdir('rubytest-pathname') {|dir|
Pathname("a/b/c/d").mkpath
assert_file.exist?("a/b/c/d")
- Pathname("a").rmtree
+ path = Pathname("a")
+ assert_equal(path, path.rmtree)
assert_file.not_exist?("a")
}
end
</code></pre>
<p>Github PR: <a href="https://github.com/ruby/ruby/pull/3705" class="external">https://github.com/ruby/ruby/pull/3705</a>. If accepted I will make a pr to update the tests here as well <a href="https://github.com/ruby/rbs/blob/b0dee64fdd00cc41c0729fa2c239fc2dcb9c3b18/test/stdlib/Pathname_test.rb#L456-L463" class="external">https://github.com/ruby/rbs/blob/b0dee64fdd00cc41c0729fa2c239fc2dcb9c3b18/test/stdlib/Pathname_test.rb#L456-L463</a>.</p> Ruby master - Feature #17291 (Assigned): Optimize __send__ callhttps://redmine.ruby-lang.org/issues/172912020-10-29T03:05:45Zmrkn (Kenta Murata)muraken@gmail.com
<p>I made a patch to optimize a <code>__send__</code> call. This optimization replaces a <code>__send__</code> method call with a call of the method whose name is the first argument of <code>__send__</code> method. The patch is available in <a href="https://github.com/ruby/ruby/pull/3720" class="external">this pull-request</a>.</p>
<p>By this change, the redefined <code>__send__</code> method is no longer called when it is called by a symbol method name. I guess it is no problem because the following warning message is displayed for a long time.</p>
<pre><code>$ ruby -e 'def __send__; end'
-e:1: warning: redefining `__send__' may cause serious problems
</code></pre>
<p>This proposal introduces two new instructions: <code>sendsym</code> and <code>opt_sendsym_without_block</code>. These instructions handle the cases that the first argument of <code>__send__</code> method is not a symbol literal. I think I can combine these two instructions into one if prefered.</p>
<p>This proposal includes the change proposed in <a class="issue tracker-2 status-1 priority-4 priority-default" title="Feature: Optimize __send__ call with a literal method name (Open)" href="https://redmine.ruby-lang.org/issues/17288">#17288</a>. I'll mark it as a duplicate of this proposal.</p>
<p>I don't handle <code>send</code> method in this proposal. The reason is that we need to examine the redefinition of <code>send</code> method in the instruction execution time. I want to discuss only <code>__send__</code> method in this ticket.</p>
<p>The benchmark result is below:</p>
<pre><code># Iteration per second (i/s)
| |compare-ruby|built-ruby|
|:----------------|-----------:|---------:|
|vm_send_sym | 18.001M| 112.208M|
| | -| 6.23x|
|vm_send_var | 17.779M| 30.922M|
| | -| 1.74x|
|vm_send_var_alt | 3.817M| 6.817M|
| | -| 1.79x|
</code></pre> Ruby master - Misc #17137 (Assigned): Cooperation on maintaining official docker ruby imageshttps://redmine.ruby-lang.org/issues/171372020-08-31T19:52:31Zdeivid (David Rodríguez)
<p>It was pointed out to me at <a href="https://github.com/docker-library/ruby/issues/323" class="external">https://github.com/docker-library/ruby/issues/323</a> that the ruby-core team has started maintaining their own docker images at <a href="https://github.com/ruby/ruby-docker-images" class="external">https://github.com/ruby/ruby-docker-images</a>, and that the base Dockerfiles were initially started from the official docker images.</p>
<p>The maintainers of the official images would be interesting in collaborating on maintaining these images. Maybe merging the projects would be a nice idea from an end user point of view. I'm guessing there's a reason why <a href="https://github.com/ruby/ruby-docker-images" class="external">https://github.com/ruby/ruby-docker-images</a> was started as a separate project, but maybe any improvements over the official project could be merged back. The obvious new feature that I see in the README is the ability to build development images of specific revisions.</p>
<p>Anyways, I mentioned the approach of the docker folks to hsbt and he told me to open a ticket here. So here it is!</p>
<p>Regards!</p> Ruby master - Feature #17111 (Assigned): Improve performance of Net::HTTPHeader#set_form by 40%https://redmine.ruby-lang.org/issues/171112020-08-10T04:09:30Ztonytonyjan (Weihang Jian)tonytonyjan@gmail.com
<a name="diff"></a>
<h2 >diff<a href="#diff" class="wiki-anchor">¶</a></h2>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/lib/net/http/header.rb b/lib/net/http/header.rb
index a8901e7..3f1a008 100644
</span><span class="gd">--- a/lib/net/http/header.rb
</span><span class="gi">+++ b/lib/net/http/header.rb
</span><span class="p">@@ -475,9 +475,8 @@</span> def set_form(params, enctype='application/x-www-form-urlencoded', formopt={})
@body = nil
@body_stream = nil
@form_option = formopt
<span class="gd">- case enctype
- when /\Aapplication\/x-www-form-urlencoded\z/i,
- /\Amultipart\/form-data\z/i
</span><span class="gi">+ case enctype.downcase
+ when 'application/x-www-form-urlencoded', 'multipart/form-data'
</span> self.content_type = enctype
else
raise ArgumentError, "invalid enctype: #{enctype}"
</code></pre>
<a name="benchmark"></a>
<h2 >benchmark<a href="#benchmark" class="wiki-anchor">¶</a></h2>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'benchmark'</span>
<span class="nb">require</span> <span class="s1">'net/http'</span>
<span class="k">module</span> <span class="nn">Net::HTTPHeader</span>
<span class="k">def</span> <span class="nf">set_form2</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="n">enctype</span> <span class="o">=</span> <span class="s1">'application/x-www-form-urlencoded'</span><span class="p">,</span> <span class="n">formopt</span> <span class="o">=</span> <span class="p">{})</span>
<span class="vi">@body_data</span> <span class="o">=</span> <span class="n">params</span>
<span class="vi">@body</span> <span class="o">=</span> <span class="kp">nil</span>
<span class="vi">@body_stream</span> <span class="o">=</span> <span class="kp">nil</span>
<span class="vi">@form_option</span> <span class="o">=</span> <span class="n">formopt</span>
<span class="k">case</span> <span class="n">enctype</span><span class="p">.</span><span class="nf">downcase</span>
<span class="k">when</span> <span class="s1">'application/x-www-form-urlencoded'</span><span class="p">,</span> <span class="s1">'multipart/form-data'</span>
<span class="nb">self</span><span class="p">.</span><span class="nf">content_type</span> <span class="o">=</span> <span class="n">enctype</span>
<span class="k">else</span>
<span class="k">raise</span> <span class="no">ArgumentError</span><span class="p">,</span> <span class="s2">"invalid enctype: </span><span class="si">#{</span><span class="n">enctype</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">500_000</span>
<span class="n">request</span> <span class="o">=</span> <span class="no">Net</span><span class="o">::</span><span class="no">HTTP</span><span class="o">::</span><span class="no">Post</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'/'</span><span class="p">)</span>
<span class="no">Benchmark</span><span class="p">.</span><span class="nf">bm</span> <span class="k">do</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span>
<span class="no">GC</span><span class="p">.</span><span class="nf">disable</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span> <span class="p">{</span> <span class="n">n</span><span class="p">.</span><span class="nf">times</span> <span class="p">{</span> <span class="n">request</span><span class="p">.</span><span class="nf">set_form</span> <span class="p">[]</span> <span class="p">}</span> <span class="p">}</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span> <span class="p">{</span> <span class="n">n</span><span class="p">.</span><span class="nf">times</span> <span class="p">{</span> <span class="n">request</span><span class="p">.</span><span class="nf">set_form2</span> <span class="p">[]</span> <span class="p">}</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<pre><code> user system total real
0.777054 0.101768 0.878822 ( 0.880472)
0.539860 0.088957 0.628817 ( 0.630178)
</code></pre>
<p>I don't see any test for <code>#set_form</code> in <code>test/net/http/test_httpheader.rb</code>, let me know if I need to add more tests, thanks!</p> Ruby master - Feature #16937 (Assigned): Add DNS over HTTP to Resolvhttps://redmine.ruby-lang.org/issues/169372020-06-07T23:46:44Zdrbrain (Eric Hodel)drbrain@segment7.net
<p>This adds a DNS over HTTP resolver at Resolv::DoH</p>
<p>It obeys RFC8484 with respect to Cache-Control and Age behavior, but does not use HTTP2 as ruby does not have an HTTP2 client.</p>
<p>It does not allow configuration of the Net::HTTP instance beyond timeouts, but I am willing to add more configuration if this is desired.</p> Ruby master - Bug #16819 (Assigned): Line reporting off by one when reporting line of a hash?https://redmine.ruby-lang.org/issues/168192020-04-27T18:18:58Zenebo (Thomas Enebo)tom.enebo@gmail.com
<p>If I run this program:</p>
<pre><code>TracePoint.new(:line) { |t| p t.lineno}.enable
def foo(a, b) # 2
a + b # 3
end # 4
# 5
foo 1, 2 # 6
# 7
A = { # 8
a: 1, # 9
b: 2 # 10
} # 11
</code></pre>
<p>I see:</p>
<pre><code>system ~/work/jruby no_sourceposition * 2388% mri26 ../snippets/ast1.rb
2
6
3
9
</code></pre>
<p>I believe this 9 should be an 8 (it is what we currently emit for JRuby). I tried to figure out why this is the case and I patched RubyVM::AbstractSyntaxTree with the ability to note newline flag:</p>
<pre><code>diff --git a/ast.c b/ast.c
index f0e8dd2eaf..df58006a96 100644
--- a/ast.c
+++ b/ast.c
@@ -7,6 +7,8 @@
#include "vm_core.h"
#include "iseq.h"
+#define RBOOL(v) ((v) ? Qtrue : Qfalse)
+
static VALUE rb_mAST;
static VALUE rb_cNode;
@@ -731,6 +733,16 @@ rb_ast_node_inspect(VALUE self)
return str;
}
+static VALUE
+rb_ast_node_newline(VALUE self)
+{
+ struct ASTNodeData *data;
+ TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
+
+ return RBOOL(data->node->flags & NODE_FL_NEWLINE);
+}
+
+
void
Init_ast(void)
{
@@ -756,5 +768,6 @@ Init_ast(void)
rb_define_method(rb_cNode, "last_lineno", rb_ast_node_last_lineno, 0);
rb_define_method(rb_cNode, "last_column", rb_ast_node_last_column, 0);
rb_define_method(rb_cNode, "children", rb_ast_node_children, 0);
+ rb_define_method(rb_cNode, "newline?", rb_ast_node_newline, 0);
rb_define_method(rb_cNode, "inspect", rb_ast_node_inspect, 0);
}
</code></pre>
<p>I also made a simple script:</p>
<pre><code>source = File.read ARGV.shift
root = RubyVM::AbstractSyntaxTree.parse source
def print_node(node, indent = "")
if node.respond_to? :first_lineno
eol = node.newline? ? " <-- newline" : ""
$stdout.write "#{indent}(#{node.type}@#{node.first_lineno-1}-#{node.last_lineno-1})"
case node.type
when :LIT, :STR
puts " = #{node.children[0].inspect}#{eol}"
when :ARRAY
puts eol
node.children[0..-2].each do |child|
print_node(child, indent + " ")
end
when :FCALL
puts " = #{node.children[0]}#{eol}"
node.children[1..-1].each do |child|
print_node(child, indent + " ")
end
else
puts eol
node.children.each do |child|
print_node(child, indent + " ")
end
end
elsif node.nil?
puts "#{indent}nil"
else
puts "#{indent}#{node.inspect}"
end
end
print_node root
puts RubyVM::InstructionSequence.compile(source).disasm
</code></pre>
<p>If I run this I see MRI has line 8 marked as the newline (which JRuby also matches) but if we look at the disasm it would appear compile.c decided to put the line in a different location:</p>
<pre><code>../ruby/ruby --disable-gems ../snippets/ast_mri.rb ../snippets/ast1.rb
(SCOPE@0-10)
[]
nil
(BLOCK@0-10)
(CALL@0-0) <-- newline
(ITER@0-0)
(CALL@0-0)
(CONST@0-0)
:TracePoint
:new
(ARRAY@0-0)
(LIT@0-0) = :line
(SCOPE@0-0)
[:t]
(ARGS@0-0)
1
nil
nil
nil
0
nil
nil
nil
nil
nil
(FCALL@0-0) = p <-- newline
(ARRAY@0-0)
(CALL@0-0)
(DVAR@0-0)
:t
:lineno
nil
:enable
nil
(DEFN@1-3) <-- newline
:foo
(SCOPE@1-3)
[:a, :b]
(ARGS@1-1)
2
nil
nil
nil
0
nil
nil
nil
nil
nil
(OPCALL@2-2) <-- newline
(LVAR@2-2)
:a
:+
(ARRAY@2-2)
(LVAR@2-2)
:b
(FCALL@5-5) = foo <-- newline
(ARRAY@5-5)
(LIT@5-5) = 1
(LIT@5-5) = 2
(CDECL@7-10) <-- newline
:A
(HASH@7-10)
(ARRAY@8-9)
(LIT@8-8) = :a
(LIT@8-8) = 1
(LIT@9-9) = :b
(LIT@9-9) = 2
== disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(11,18)> (catch: FALSE)
== catch table
| catch type: break st: 0000 ed: 0013 sp: 0000 cont: 0013
| == disasm: #<ISeq:block in <compiled>@<compiled>:1 (1,22)-(1,39)> (catch: FALSE)
| == catch table
| | catch type: redo st: 0001 ed: 0010 sp: 0000 cont: 0001
| | catch type: next st: 0001 ed: 0010 sp: 0000 cont: 0010
| |------------------------------------------------------------------------
| local table (size: 1, argc: 1 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
| [ 1] t@0<Arg>
| 0000 nop ( 1)[Bc]
| 0001 putself [Li]
| 0002 getlocal_WC_0 t@0
| 0004 opt_send_without_block <callinfo!mid:lineno, argc:0, ARGS_SIMPLE>, <callcache>
| 0007 opt_send_without_block <callinfo!mid:p, argc:1, FCALL|ARGS_SIMPLE>, <callcache>
| 0010 nop
| 0011 leave ( 1)[Br]
|------------------------------------------------------------------------
0000 opt_getinlinecache 7, <is:0> ( 1)[Li]
0003 getconstant :TracePoint
0005 opt_setinlinecache <is:0>
0007 putobject :line
0009 send <callinfo!mid:new, argc:1>, <callcache>, block in <compiled>
0013 nop
0014 opt_send_without_block <callinfo!mid:enable, argc:0, ARGS_SIMPLE>, <callcache>( 1)
0017 pop
0018 putspecialobject 1 ( 2)[Li]
0020 putobject :foo
0022 putiseq foo
0024 opt_send_without_block <callinfo!mid:core#define_method, argc:2, ARGS_SIMPLE>, <callcache>
0027 pop
0028 putself ( 6)[Li]
0029 putobject_INT2FIX_1_
0030 putobject 2
0032 opt_send_without_block <callinfo!mid:foo, argc:2, FCALL|ARGS_SIMPLE>, <callcache>
0035 pop
0036 duphash {:a=>1, :b=>2} ( 9)[Li]
0038 dup ( 8)
0039 putspecialobject 3
0041 setconstant :A
0043 leave
== disasm: #<ISeq:foo@<compiled>:2 (2,0)-(4,3)> (catch: FALSE)
local table (size: 2, argc: 2 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1])
[ 2] a@0<Arg> [ 1] b@1<Arg>
0000 getlocal_WC_0 a@0 ( 3)[LiCa]
0002 getlocal_WC_0 b@1
0004 opt_plus <callinfo!mid:+, argc:1, ARGS_SIMPLE>, <callcache>
0007 leave ( 4)[Re]
</code></pre> Ruby master - Misc #16805 (Assigned): Coroutine's license is unclearhttps://redmine.ruby-lang.org/issues/168052020-04-21T10:23:49Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<p>Files under <code>coroutine/</code> start like this:</p>
<pre><code class="C syntaxhl" data-language="C"><span class="o">/*</span>
<span class="o">*</span> <span class="n">This</span> <span class="n">file</span> <span class="n">is</span> <span class="n">part</span> <span class="n">of</span> <span class="n">the</span> <span class="s">"Coroutine"</span> <span class="n">project</span> <span class="n">and</span> <span class="n">released</span> <span class="n">under</span> <span class="n">the</span> <span class="n">MIT</span> <span class="n">License</span><span class="p">.</span>
<span class="o">*</span>
</code></pre>
<p>The problem is, there is no definition of "the MIT License" throughout the entire project.</p>
<p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/3344">@ioquatix (Samuel Williams)</a> can you add your terms somewhere inside of LEGAL? There are several other materials also under the MIT license. You can follow how they are listed up.</p> Ruby master - Bug #16776 (Assigned): Regression in coverage libraryhttps://redmine.ruby-lang.org/issues/167762020-04-10T16:39:29Zdeivid (David Rodríguez)
<p>Hi!</p>
<p>I noticed a regression in the coverage library. I tried to write a minimal program to show it, hopefully it gives some clues or where the issue might lie.</p>
<p>In ruby 2.5.8 and earlier, the following program would print <code>{:lines=>[1, 1, nil]}</code>, showing that the body of the "foo" method was run once. However, on newer rubies, it prints <code>{:lines=>[1, 0, nil]}</code>, which is incorrect because the "foo" method body has actually been run once.</p>
<p>This is the repro script:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># frozen_string_literal: true</span>
<span class="nb">require</span> <span class="s2">"coverage"</span>
<span class="no">Coverage</span><span class="p">.</span><span class="nf">start</span><span class="p">(</span><span class="ss">lines: </span><span class="kp">true</span><span class="p">)</span>
<span class="n">code</span> <span class="o">=</span> <span class="o"><<~</span><span class="no">RUBY</span><span class="sh">
def foo
"LOL"
end
</span><span class="no">RUBY</span>
<span class="no">File</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="s2">"foo.rb"</span><span class="p">,</span> <span class="s2">"w"</span><span class="p">)</span> <span class="p">{</span> <span class="o">|</span><span class="n">f</span><span class="o">|</span> <span class="n">f</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="n">code</span><span class="p">)</span> <span class="p">}</span>
<span class="nb">require_relative</span> <span class="s2">"foo"</span>
<span class="no">TracePoint</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">:line</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">_tp</span><span class="o">|</span>
<span class="n">foo</span>
<span class="k">end</span><span class="p">.</span><span class="nf">enable</span> <span class="k">do</span>
<span class="nb">sleep</span> <span class="mi">0</span>
<span class="k">end</span>
<span class="n">res</span> <span class="o">=</span> <span class="no">Coverage</span><span class="p">.</span><span class="nf">result</span>
<span class="nb">puts</span> <span class="n">res</span><span class="p">[</span><span class="no">File</span><span class="p">.</span><span class="nf">expand_path</span><span class="p">(</span><span class="s2">"foo.rb"</span><span class="p">)]</span>
</code></pre> Ruby master - Misc #16747 (Assigned): Repository reorganization requesthttps://redmine.ruby-lang.org/issues/167472020-04-01T06:58:09Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<p>Back in 0.49, there were only 60 files and 3 directories at the root of this project. This was already at some level, but OK-ish. Now, as we are reaching 3.0, we currently have 167 files and 26 directories. The project has grown up. I believe we need some housekeeping.</p>
<p>I would like to introduce directories and move things around, like <a href="https://github.com/jemalloc/jemalloc/" class="external">what they do for jemalloc</a>.</p>
<ul>
<li>Create directory named <code>src</code> and move sources there.</li>
</ul>
<p>There is no need to cargo-cult them so suggestions are welcome.</p> Ruby master - Feature #16657 (Assigned): Don't ship bundled gems as .gem files as well as in expa...https://redmine.ruby-lang.org/issues/166572020-02-27T06:50:02Zvo.x (Vit Ondruch)v.ondruch@tiscali.cz
<p>Working at <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Extensions Do Not Compile on Mingw64 with mingw32-make (Closed)" href="https://redmine.ruby-lang.org/issues/16651">#16651</a>, I wonder why the release tarball ships with the bundled gem in form of .gem packages as well as the expanded sources. It would be nice, if one option is chosen. Ideally just the .gem packages, because these are vanilla upstream packages installable via RubyGems without rbinstall magic.</p> Ruby master - Misc #16630 (Assigned): Deprecate pub/ruby/*snapshot* and use pub/ruby/snapshot/* i...https://redmine.ruby-lang.org/issues/166302020-02-13T08:51:43Zznz (Kazuhiro NISHIYAMA)
<p>In <a href="https://www.ruby-lang.org/en/downloads/" class="external">https://www.ruby-lang.org/en/downloads/</a>, snapshots links to <code>pub/ruby/snapshot.*</code> and <code>pub/ruby/stable-snapshot.*</code> as official snapshot tarballs now.</p>
<p>I want to change links to snapshot tarballs in <a href="https://cache.ruby-lang.org/pub/ruby/snapshot/" class="external">https://cache.ruby-lang.org/pub/ruby/snapshot/</a>.</p>
<p>They created by <a href="https://github.com/ruby/actions/" class="external">https://github.com/ruby/actions/</a> now.</p>
<p>Tarballs under <code>pub/ruby/snapshot/</code> have branch name (e.g. <code>ruby_2_7</code>) in filenames.<br>
And they are tested. (but they remain even if tests failed.)</p>
<p><code>pub/ruby/*snapshot.*</code> are not tested.<br>
And there are fewer files under <code>pub/ruby/</code> without sub-directory recently. (e.g. <code>ruby- 2.7.*</code> are in <code>pub/ruby/2.7/</code> only.)<br>
So I want to remove them.</p>
<p>Because of the plan, <code>stable-snapshot.*</code> are still snapshot of <code>ruby_2_6</code> instead of <code>ruby_2_7</code>.</p> Ruby master - Misc #16512 (Assigned): Improving `www.ruby-lang.org` reference by merging with `ru...https://redmine.ruby-lang.org/issues/165122020-01-16T08:38:13Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/710">@zverok (Victor Shepelev)</a> prepared better-looking reference pages at <code>rubyreferences.github.io</code>. I think there's room for improvement of reference pages on <code>www.ruby-lang.org</code>. <a class="user active user-mention" href="https://redmine.ruby-lang.org/users/572">@hsbt (Hiroshi SHIBATA)</a> Is there a chance to work with?</p>
<p>Matz.</p> Ruby master - Bug #16497 (Assigned): StringIO#internal_encoding is broken (more severely in 2.7)https://redmine.ruby-lang.org/issues/164972020-01-10T11:18:31Zzverok (Victor Shepelev)zverok.offline@gmail.com
<p>To the best of my understanding from <a href="https://docs.ruby-lang.org/en/master/Encoding.html" class="external">Encoding</a> docs, the following is true:</p>
<ul>
<li>external encoding (explicitly specified or taken from <code>Encoding.default_external</code>) specifies how the IO understands input and stores it internally</li>
<li>internal encoding (explicitly specified or taken from <code>Encoding.default_internal</code>) specifies how the IO converts what it reads.</li>
</ul>
<p>Demonstration with regular files:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># prepare data</span>
<span class="no">File</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="s1">'test.txt'</span><span class="p">,</span> <span class="s1">'Україна'</span><span class="p">.</span><span class="nf">encode</span><span class="p">(</span><span class="s1">'KOI8-U'</span><span class="p">),</span> <span class="ss">encoding: </span><span class="s1">'KOI8-U'</span><span class="p">)</span> <span class="c1">#=> 7</span>
<span class="k">def</span> <span class="nf">test</span><span class="p">(</span><span class="n">io</span><span class="p">)</span>
<span class="n">str</span> <span class="o">=</span> <span class="n">io</span><span class="p">.</span><span class="nf">read</span>
<span class="p">[</span><span class="n">io</span><span class="p">.</span><span class="nf">external_encoding</span><span class="p">,</span> <span class="n">io</span><span class="p">.</span><span class="nf">internal_encoding</span><span class="p">,</span> <span class="n">str</span><span class="p">,</span> <span class="n">str</span><span class="p">.</span><span class="nf">encoding</span><span class="p">]</span>
<span class="k">end</span>
<span class="c1"># read it:</span>
<span class="nb">test</span><span class="p">(</span><span class="no">File</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="s1">'test.txt'</span><span class="p">,</span> <span class="s1">'r:KOI8-U'</span><span class="p">))</span>
<span class="c1"># => [#<Encoding:KOI8-U>, nil, "\xF5\xCB\xD2\xC1\xA7\xCE\xC1", #<Encoding:KOI8-U>]</span>
<span class="c1"># We can specify internal encoding when opening the file:</span>
<span class="nb">test</span><span class="p">(</span><span class="no">File</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="s1">'test.txt'</span><span class="p">,</span> <span class="s1">'r:KOI8-U:UTF-8'</span><span class="p">))</span>
<span class="c1"># => [#<Encoding:KOI8-U>, #<Encoding:UTF-8>, "Україна", #<Encoding:UTF-8>]</span>
<span class="c1"># ...or when it is already opened</span>
<span class="nb">test</span><span class="p">(</span><span class="no">File</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="s1">'test.txt'</span><span class="p">).</span><span class="nf">tap</span> <span class="p">{</span> <span class="o">|</span><span class="n">f</span><span class="o">|</span> <span class="n">f</span><span class="p">.</span><span class="nf">set_encoding</span><span class="p">(</span><span class="s1">'KOI8-U'</span><span class="p">,</span> <span class="s1">'UTF-8'</span><span class="p">)</span> <span class="p">})</span>
<span class="c1"># => [#<Encoding:KOI8-U>, #<Encoding:UTF-8>, "Україна", #<Encoding:UTF-8>]</span>
<span class="c1"># ...or with Encoding.default_internal</span>
<span class="no">Encoding</span><span class="p">.</span><span class="nf">default_internal</span> <span class="o">=</span> <span class="s1">'UTF-8'</span>
<span class="nb">test</span><span class="p">(</span><span class="no">File</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="s1">'test.txt'</span><span class="p">,</span> <span class="s1">'r:KOI8-U'</span><span class="p">))</span>
<span class="c1"># => [#<Encoding:KOI8-U>, #<Encoding:UTF-8>, "Україна", #<Encoding:UTF-8>]</span>
</code></pre>
<p>But with StringIO, <strong>internal encoding can't be set</strong> in Ruby <strong>2.6</strong>:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'stringio'</span>
<span class="no">Encoding</span><span class="p">.</span><span class="nf">default_internal</span> <span class="o">=</span> <span class="kp">nil</span>
<span class="n">str</span> <span class="o">=</span> <span class="s1">'Україна'</span><span class="p">.</span><span class="nf">encode</span><span class="p">(</span><span class="s1">'KOI8-U'</span><span class="p">)</span>
<span class="c1"># Simplest form:</span>
<span class="nb">test</span><span class="p">(</span><span class="no">StringIO</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">str</span><span class="p">))</span>
<span class="c1"># => [#<Encoding:KOI8-U>, nil, "\xF5\xCB\xD2\xC1\xA7\xCE\xC1", #<Encoding:KOI8-U>]</span>
<span class="c1"># Try to set via mode</span>
<span class="nb">test</span><span class="p">(</span><span class="no">StringIO</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">str</span><span class="p">,</span> <span class="s1">'r:KOI8-U:UTF-8'</span><span class="p">))</span>
<span class="c1"># => [#<Encoding:KOI8-U>, nil, "\xF5\xCB\xD2\xC1\xA7\xCE\xC1", #<Encoding:KOI8-U>]</span>
<span class="c1"># Try to set via set_encoding:</span>
<span class="nb">test</span><span class="p">(</span><span class="no">StringIO</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">str</span><span class="p">,</span> <span class="s1">'r:KOI8-U:UTF-8'</span><span class="p">).</span><span class="nf">tap</span> <span class="p">{</span> <span class="o">|</span><span class="n">f</span><span class="o">|</span> <span class="n">f</span><span class="p">.</span><span class="nf">set_encoding</span><span class="p">(</span><span class="s1">'KOI8-U'</span><span class="p">,</span> <span class="s1">'UTF-8'</span><span class="p">)</span> <span class="p">})</span>
<span class="c1"># => [#<Encoding:KOI8-U>, nil, "\xF5\xCB\xD2\xC1\xA7\xCE\xC1", #<Encoding:KOI8-U>]</span>
<span class="c1"># Try to set via Enoding.default_internal:</span>
<span class="no">Encoding</span><span class="p">.</span><span class="nf">default_internal</span> <span class="o">=</span> <span class="s1">'UTF-8'</span>
<span class="nb">test</span><span class="p">(</span><span class="no">StringIO</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">str</span><span class="p">))</span>
<span class="c1"># => [#<Encoding:KOI8-U>, nil, "\xF5\xCB\xD2\xC1\xA7\xCE\xC1", #<Encoding:KOI8-U>]</span>
</code></pre>
<p>So, in 2.6, any attempt to do something with StringIO's internal encoding are <strong>just ignored</strong>.</p>
<p>In <strong>2.7</strong>, though, matters became much worse:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'stringio'</span>
<span class="no">Encoding</span><span class="p">.</span><span class="nf">default_internal</span> <span class="o">=</span> <span class="kp">nil</span>
<span class="n">str</span> <span class="o">=</span> <span class="s1">'Україна'</span><span class="p">.</span><span class="nf">encode</span><span class="p">(</span><span class="s1">'KOI8-U'</span><span class="p">)</span>
<span class="c1"># Behaves same as 2.6</span>
<span class="nb">test</span><span class="p">(</span><span class="no">StringIO</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">str</span><span class="p">))</span>
<span class="c1"># => [#<Encoding:KOI8-U>, nil, "\xF5\xCB\xD2\xC1\xA7\xCE\xC1", #<Encoding:KOI8-U>]</span>
<span class="c1"># Try to set via mode: WEIRD behavior starts</span>
<span class="nb">test</span><span class="p">(</span><span class="no">StringIO</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">str</span><span class="p">,</span> <span class="s1">'r:KOI8-U:UTF-8'</span><span class="p">))</span>
<span class="c1"># => [#<Encoding:UTF-8>, nil, "\xF5\xCB\xD2\xC1\xA7\xCE\xC1", #<Encoding:UTF-8>]</span>
<span class="c1"># Try to set via set_encoding: still just ignored</span>
<span class="nb">test</span><span class="p">(</span><span class="no">StringIO</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">str</span><span class="p">,</span> <span class="s1">'r:KOI8-U:UTF-8'</span><span class="p">).</span><span class="nf">tap</span> <span class="p">{</span> <span class="o">|</span><span class="n">f</span><span class="o">|</span> <span class="n">f</span><span class="p">.</span><span class="nf">set_encoding</span><span class="p">(</span><span class="s1">'KOI8-U'</span><span class="p">,</span> <span class="s1">'UTF-8'</span><span class="p">)</span> <span class="p">})</span>
<span class="c1"># => [#<Encoding:KOI8-U>, nil, "\xF5\xCB\xD2\xC1\xA7\xCE\xC1", #<Encoding:KOI8-U>]</span>
<span class="c1"># Try to set via Enoding.default_internal: WEIRD behavior again</span>
<span class="no">Encoding</span><span class="p">.</span><span class="nf">default_internal</span> <span class="o">=</span> <span class="s1">'UTF-8'</span>
<span class="nb">test</span><span class="p">(</span><span class="no">StringIO</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">str</span><span class="p">))</span>
<span class="c1"># => [#<Encoding:UTF-8>, nil, "\xF5\xCB\xD2\xC1\xA7\xCE\xC1", #<Encoding:UTF-8>]</span>
</code></pre>
<p>So, <strong>2.7</strong> not just ignores attempts to set <strong>internal</strong> encoding, but erroneously sets it to <strong>external</strong> one, so strings are not recoded, but their encoding is forced to change.</p>
<p>I believe it is severe bug (more severe than 2.6's "just ignoring").</p>
<p><a href="https://www.reddit.com/r/ruby/comments/emd6q4/is_this_a_stringio_bug_in_ruby_270/" class="external">This Reddit thread</a> shows how it breaks existing code:</p>
<ul>
<li>the author uses <code>StringIO</code> to work with <code>ASCII-8BIT</code> strings;</li>
<li>the code is performed in Rails environment (which sets <code>internal_encoding</code> to <code>UTF-8</code> by default);</li>
<li>under <strong>2.7</strong>, <code>StringIO#read</code> returns <code>ASCII-8BIT</code> content in Strings saying their encoding is <code>UTF-8</code>.</li>
</ul> Ruby master - Feature #16461 (Assigned): Proc#usinghttps://redmine.ruby-lang.org/issues/164612019-12-28T03:32:34Zshugo (Shugo Maeda)
<a name="Overview"></a>
<h2 >Overview<a href="#Overview" class="wiki-anchor">¶</a></h2>
<p>I propose Proc#using to support block-level refinements.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">IntegerDivExt</span>
<span class="n">refine</span> <span class="no">Integer</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">/</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="n">quo</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">instance_eval_with_integer_div_ext</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="n">block</span><span class="p">.</span><span class="nf">using</span><span class="p">(</span><span class="no">IntegerDivExt</span><span class="p">)</span> <span class="c1"># using IntegerDivExt in the block represented by the Proc object</span>
<span class="n">obj</span><span class="p">.</span><span class="nf">instance_eval</span><span class="p">(</span><span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="k">end</span>
<span class="c1"># necessary where blocks are defined (not where Proc#using is called)</span>
<span class="n">using</span> <span class="no">Proc</span><span class="o">::</span><span class="no">Refinements</span>
<span class="nb">p</span> <span class="mi">1</span> <span class="o">/</span> <span class="mi">2</span> <span class="c1">#=> 0</span>
<span class="n">instance_eval_with_integer_div_ext</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="k">do</span>
<span class="nb">p</span> <span class="nb">self</span> <span class="o">/</span> <span class="mi">2</span> <span class="c1">#=> (1/2)</span>
<span class="k">end</span>
<span class="nb">p</span> <span class="mi">1</span> <span class="o">/</span> <span class="mi">2</span> <span class="c1">#=> 0</span>
</code></pre>
<a name="PoC-implementation"></a>
<h2 >PoC implementation<a href="#PoC-implementation" class="wiki-anchor">¶</a></h2>
<p>For CRuby: <a href="https://github.com/shugo/ruby/pull/2" class="external">https://github.com/shugo/ruby/pull/2</a><br>
For JRuby: <a href="https://github.com/shugo/jruby/pull/1" class="external">https://github.com/shugo/jruby/pull/1</a></p>
<a name="Background"></a>
<h2 >Background<a href="#Background" class="wiki-anchor">¶</a></h2>
<p>I proposed <a href="https://bugs.ruby-lang.org/issues/12086" class="external">Feature #12086: using: option for instance_eval etc.</a> before, but it has problems:</p>
<ul>
<li>Thread safety: The same block can be invoked with different refinements in multiple threads, so it's hard to implement method caching.</li>
<li>_exec family support: {instance,class,module}_exec cannot be supported.</li>
<li>Implicit use of refinements: every blocks can be used with refinements, so there was implementation difficulty in JRuby and it has usability issue in headius's opinion.</li>
</ul>
<a name="Solutions-in-this-proposal"></a>
<h2 >Solutions in this proposal<a href="#Solutions-in-this-proposal" class="wiki-anchor">¶</a></h2>
<a name="Thread-safety"></a>
<h3 >Thread safety<a href="#Thread-safety" class="wiki-anchor">¶</a></h3>
<p>Proc#using affects the block represented by the Proc object, neither the specific Proc object nor the specific block invocation.<br>
Method calls in a block are resolved with refinements which are used by Proc#using in the block at the time.<br>
Once all possible refinements are used in the block, there is no need to invalidate method cache anymore.</p>
<p>See <a href="https://github.com/shugo/ruby/pull/2/commits/1c922614ad7d1fb43b73e195348c81da7a4546ef" class="external">these tests</a> to understand how it works.<br>
Which refinements are used is depending on the order of Proc#using invocations until all Proc#using calls are finished, but eventually method calls in a block are resolved with the same refinements.</p>
<a name="-_exec-family-support"></a>
<h3 >* _exec family support<a href="#-_exec-family-support" class="wiki-anchor">¶</a></h3>
<p><a href="https://bugs.ruby-lang.org/issues/12086" class="external">Feature #12086</a> was an extension of _eval family, so it cannot be used with _exec family, but Proc#using is independent from _eval family, and can be used with _exec family:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">instance_exec_with_integer_div_ext</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="n">block</span><span class="p">.</span><span class="nf">using</span><span class="p">(</span><span class="no">IntegerDivExt</span><span class="p">)</span>
<span class="n">obj</span><span class="p">.</span><span class="nf">instance_exec</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">using</span> <span class="no">Proc</span><span class="o">::</span><span class="no">Refinements</span>
<span class="nb">p</span> <span class="mi">1</span> <span class="o">/</span> <span class="mi">2</span> <span class="c1">#=> 0</span>
<span class="n">instance_exec_with_integer_div_ext</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">other</span><span class="o">|</span>
<span class="nb">p</span> <span class="nb">self</span> <span class="o">/</span> <span class="n">other</span> <span class="c1">#=> (1/2)</span>
<span class="k">end</span>
<span class="nb">p</span> <span class="mi">1</span> <span class="o">/</span> <span class="mi">2</span> <span class="c1">#=> 0</span>
</code></pre>
<a name="Implicit-use-of-refinements"></a>
<h3 >Implicit use of refinements<a href="#Implicit-use-of-refinements" class="wiki-anchor">¶</a></h3>
<p>Proc#using can be used only if <code>using Proc::Refinements</code> is called in the scope of the block represented by the Proc object.<br>
Otherwise, a RuntimeError is raised.</p>
<p>There are two reasons:</p>
<ul>
<li>JRuby creates a special CallSite for refinements at compile-time only when <code>using</code> is called at the scope.</li>
<li>When reading programs, it may help understanding behavior. IMHO, it may be unnecessary if libraries which uses Proc#using are well documented.</li>
</ul>
<p><code>Proc::Refinements</code> is a dummy module, and has no actual refinements.</p> Ruby master - Feature #16350 (Assigned): ArithmeticSequence#member? can result in infinite loophttps://redmine.ruby-lang.org/issues/163502019-11-16T17:20:32Zparker (Parker Finch)
<p>I'm not sure if this is a bug or a feature, it feels somewhere in between.</p>
<p>This is my first time contributing to the Ruby code, let me know what I can improve in this report!</p>
<p>ArithmeticSequence#member? enumerates through the sequence in order to determine if an element is included. (It just uses Enumerable#member?.) This leads to an infinite loop if the sequence is infinite and the element is not included, such as <code>1.step.member?(0)</code>.</p>
<p>I expected <code>1.step.member?(0)</code> to return <code>false</code>.</p>
<p>Since ArithmeticSequences are much more constrained than regular Enumerables, the #member? method can be overridden to efficiently determine if an element is included in the sequence.</p>
<p>I started implementing this change (patch attached) but got a little confused when trying to handle floats. Before digging in too deeply, I wanted to check if this is a change that will be accepted.</p>
<p>Let me know if I should keep looking into this!</p> Ruby master - Misc #16124 (Assigned): Let the transient heap belong to objspacehttps://redmine.ruby-lang.org/issues/161242019-08-24T12:41:53Zmethodmissing (Lourens Naudé)lourens@bearmetal.eu
<p>As per comment from Nobu in <a href="https://github.com/ruby/ruby/pull/2303#issuecomment-523248875" class="external">https://github.com/ruby/ruby/pull/2303#issuecomment-523248875</a> , I took an initial stab @ a tighter integration between objspace and the transient heap in <a href="https://github.com/ruby/ruby/pull/2400" class="external">https://github.com/ruby/ruby/pull/2400</a></p>
<a name="Benefits"></a>
<h3 >Benefits<a href="#Benefits" class="wiki-anchor">¶</a></h3>
<ul>
<li>Multi-VM (MVM) friendly - ( vm -> objspace -> theap )</li>
<li>The 32MB (current size) arena lazy allocated on ruby init is now properly freed on shutdown as well</li>
<li>It feels strange that the evacuation from the current global theap is to objspace, whereas the space evacuated from is a global arena.</li>
</ul>
<a name="Not-so-great"></a>
<h3 >Not so great<a href="#Not-so-great" class="wiki-anchor">¶</a></h3>
<ul>
<li>A fast reference to a global variable <code>global_transient_heap</code> becomes a function call to <code>rb_objspace_get_theap()</code> and related pointer chasing from vm -> objspace -> theap</li>
<li>Some internal transient heap structs moved to the header file now leaks into all other reference sites where this source file (<code>transient_heap.c</code>) as previously just used for API</li>
<li>I'm not sure exactly of the boundary Koichi had in mind for the GC compile module and how tightly it should (or shouldn't) be coupled to the transient heap. <code>struct rb_objspace*</code> declarations elsewhere for example reveals nothing about the structure members for example, whereas with this PR a lot of transient heap internals are exposed via the header file now</li>
<li>Also possible to move <code>transient_heap.c</code> into <code>gc.c</code> - I feel theap is not an experimental feature anymore and has been stable for quite some time with plausible performance benefits. The downside of that is <code>gc.c</code> is quite dense already, but then all ruby heap management concerns belong to one compile unit.</li>
</ul>
<p>In a similar vein the global method cache could perhaps belong to the VM instance as well, effectively better alignment with MVM and also easier to have a balanced VM setup and teardown sequence without anything left dangling on ruby shutdown.</p>
<p>Thoughts?</p> Ruby master - Feature #16027 (Assigned): Update Ruby's dtrace / USDT API to match what is exposed...https://redmine.ruby-lang.org/issues/160272019-07-27T17:22:38Zdalehamel (Dale Hamel)
<a name="Abstract"></a>
<h1 >Abstract<a href="#Abstract" class="wiki-anchor">¶</a></h1>
<p>I propose that Ruby's "dtrace" support be extended to match what is available in the TracePoint API, as was the case until feature [Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Accept "target" keyword on `TracePoint#enable` (Closed)" href="https://redmine.ruby-lang.org/issues/15289">#15289</a>] landed.</p>
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p>I will refer to Ruby's "dtrace" bindings as USDT bindings for simplicity, as this is the typo of dtrace probe that they support.</p>
<p>Prior to [Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Accept "target" keyword on `TracePoint#enable` (Closed)" href="https://redmine.ruby-lang.org/issues/15289">#15289</a>] being merged, Ruby's tracepoint API was able to trace only 'all' instances of a type of event.</p>
<p>Ruby added support for tracing ruby with dtrace, and so Ruby's USDT Ruby TracePoint API were "in sync".</p>
<p>Once the Ruby TracePoint API recently added the ability to do filtered tracing in [Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Accept "target" keyword on `TracePoint#enable` (Closed)" href="https://redmine.ruby-lang.org/issues/15289">#15289</a>], it added new functionality but brought the TracePoint and USDT API out of sync.</p>
<p>Currently the TracePoint API is ahead of the USDT API, which presents the problem. There is valuable debug information available, but we do not have<br>
a way to access it with dtrace instrumentation.</p>
<p>Additionally, the recent release of bpftrace adds support for USDT tracing on linux, which makes this a valuable opportunity to be able to use Ruby's TracePoint API in an efficient and targeted way for production tracing. To achieve this, we must synchronize the features of the USDT and TracePoint API.</p>
<p>What is currently lacking is the ability to do filtered, selective tracing as the <code>TracePoint#enable</code> call now supports as per <a href="https://github.com/ruby/ruby/blob/master/prelude.rb#L141" class="external">prelude.rb#L141</a></p>
<a name="Proposal"></a>
<h1 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h1>
<p>When enabling a TracePoint, users can specify a flag: <code>usdt: [LIST_OF_SIMPLE_TYPES]</code>, which will trigger Ruby to also enable the USDT API for when it enables TracePoints.</p>
<p>Within the TracePoint block, users can call <code>tp.fire</code> to send USDT data. So the new default API is:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">trace</span><span class="p">.</span><span class="nf">enable</span><span class="p">(</span><span class="ss">target: </span><span class="kp">nil</span><span class="p">,</span> <span class="ss">target_line: </span><span class="kp">nil</span><span class="p">,</span> <span class="ss">target_thread: nil: usdt: </span><span class="kp">nil</span><span class="p">)</span>
</code></pre>
<p>And the usage might look like:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">trace</span><span class="p">.</span><span class="nf">enable</span><span class="p">(</span><span class="ss">target: </span><span class="nb">method</span><span class="p">(</span><span class="ss">:foo</span><span class="p">),</span> <span class="ss">target_line: </span><span class="mi">5</span><span class="p">,</span> <span class="ss">usdt: </span><span class="p">[</span><span class="no">Integer</span><span class="p">,</span> <span class="no">String</span><span class="p">])</span> <span class="k">do</span> <span class="o">|</span><span class="n">tp</span><span class="o">|</span>
<span class="n">tp</span><span class="p">.</span><span class="nf">fire</span><span class="p">(</span><span class="n">tp</span><span class="p">.</span><span class="nf">lineno</span><span class="p">,</span> <span class="s2">"Any String I want to send"</span><span class="p">)</span>
<span class="k">end</span>
</code></pre>
<p>The types specified must be simple types such as <code>Integer</code> or <code>String</code>, given by their names as constants. When data to the tracepoint, the types must match. If they don't, the tracer won't be able to interpret them properly, but nothing should crash.</p>
<a name="Details"></a>
<h1 >Details<a href="#Details" class="wiki-anchor">¶</a></h1>
<p>I propose that Ruby optionally generate ELF (Linux) or DOF (Darwin) annotations for TracePoint targets when they are enabled.</p>
<p>As ruby is a dynamic language, it cannot do this natively (yet) though Ruby JIT may make this easier, but for now it is not suitable for production use.</p>
<p>To get around this, Ruby can either generate the DOF or ELF stub shared library itself, for example it may do one per class, treating the class as the "provider" for the USDT API, and the methods as tracepoints. This is the approach used by <a href="https://github.com/chrisa/libusdt" class="external">libusdt</a>, which generates DOF usable on Darwin, BSD, and other platforms, and <a href="https://github.com/sthima/libstapsdt" class="external">libstapsdt</a>, which generates ELF stubs for use on linux.</p>
<p>When a tracepoint is triggered, the user may be able to call a new API <code>TracePoint#fire</code>, to send data to the Kernel via the USDT API, using the generated ELF stub as a bridge, giving the kernel an address to target in order to receive this data.</p>
<p>Upon enabling a tracepoint, we can either generate these stubs internally, or by linking to an external library that must be enabled at configure time (without this, USDT tracing wouldn't be enabled at all).</p>
<p>It may be possible to use the existing bridge that is used by ruby jit, or have an experimental flag such as <code>--usdt</code> that enables support for generating these stubs.</p>
<p>It may be more consistent with the future Ruby JIT to do this, or else Ruby can generate these stubs by its own native code, but this will require a sort of merging of libusdt and libstapsdt. This would add a dependency to the libelf development header, but that is probably not a problem on Linux platforms.</p>
<p>I would suggest the first approach, if this feature is accepted, would be to try and implement the ELF / DOF generation directly in Ruby. What libstapsdt and libusdt do isn't that complex and could be done in its own C file that probably wouldn't be too large.</p>
<p>Failing that approach, it may be worth investigating the Ruby JIT code to see if a compiler can generate these stubs for us easily. This approach would be to have ruby generate C code that results in the necessary DOF/ELF annotations, and have the compiler pipeline used by ruby JIT to generate the file. This couples the feature to ruby jit though.</p>
<a name="Usecase"></a>
<h1 >Usecase<a href="#Usecase" class="wiki-anchor">¶</a></h1>
<p>This feature would be used by dtrace / bpftrace users to debug ruby applications. It may be possible for other platforms to benefit from this too, but I think the main use case is for Linux system administrators and developers to use external debuggers (dtrace/bpftrace) to introspect Ruby's behavior.</p>
<a name="Discussion"></a>
<h1 >Discussion<a href="#Discussion" class="wiki-anchor">¶</a></h1>
<a name="Pros"></a>
<h2 >Pros:<a href="#Pros" class="wiki-anchor">¶</a></h2>
<ul>
<li>Syncs the Ruby TracePoint and USDT API</li>
<li>Allows for much more dynamic and targeted USDT tracing</li>
<li>Can help to find problems in both development and production</li>
<li>Can be used for performance and error analysis</li>
<li>Is better than printing, as emitting/collecting data is only done while a "debugger is attached"</li>
</ul>
<a name="Cons"></a>
<h2 >Cons:<a href="#Cons" class="wiki-anchor">¶</a></h2>
<ul>
<li>Complexity introduced, in order to generate the ELF/DOF stub files</li>
<li>Not easily ported to other platforms</li>
<li>Isn't fully consistent with the current dtrace functionality of Ruby, which is built-in to the VM</li>
</ul>
<a name="Limitation"></a>
<h1 >Limitation<a href="#Limitation" class="wiki-anchor">¶</a></h1>
<p>This will only work on *Nix platforms, and probably just on Linux to start, as that is where most of the benefits are.</p>
<p>If the Ruby JIT approach is preferred or much simpler, then that functionality will be tied to the Ruby JIT functionality.</p>
<a name="See-also"></a>
<h1 >See also<a href="#See-also" class="wiki-anchor">¶</a></h1>
<ul>
<li>
<a href="https://bpf.sh/usdt-report-doc/index.html" class="external">https://bpf.sh/usdt-report-doc/index.html</a> a document describing my experimental gem ruby-static-tracing, which prototypes this functionality outside of the RubyVM</li>
<li>
<a href="https://bpf.sh/production-breakpoints-doc/index.html" class="external">https://bpf.sh/production-breakpoints-doc/index.html</a> a work-in-progress on adding more dynamic method and line based USDT tracing to ruby, built atop ruby-static-tracing now using the ruby tracepoint API.</li>
</ul> Ruby master - Misc #16025 (Assigned): 'st_check_for_sizeof_st_index_t' declared as array with a n...https://redmine.ruby-lang.org/issues/160252019-07-27T05:32:44Zvadimp (Vadim Peretokin)
<p>Compilation of st.h with Emscripten 1.38.30 fails:</p>
<pre><code class="c syntaxhl" data-language="c"><span class="n">st</span><span class="p">.</span><span class="n">h</span><span class="o">:</span><span class="mi">65</span><span class="o">:</span><span class="mi">45</span><span class="o">:</span> <span class="n">error</span><span class="o">:</span> <span class="err">'</span><span class="n">st_check_for_sizeof_st_index_t</span><span class="err">'</span> <span class="n">declared</span> <span class="n">as</span> <span class="n">an</span>
<span class="n">array</span> <span class="n">with</span> <span class="n">a</span> <span class="n">negative</span> <span class="n">size</span>
<span class="k">typedef</span> <span class="kt">char</span> <span class="n">st_check_for_sizeof_st_index_t</span><span class="p">[</span><span class="n">SIZEOF_VOIDP</span> <span class="o">==</span> <span class="p">(</span><span class="kt">int</span><span class="p">)</span><span class="k">sizeof</span><span class="p">(</span><span class="n">st_index_t</span><span class="p">)</span> <span class="o">?</span> <span class="mi">1</span> <span class="o">:</span> <span class="o">-</span><span class="mi">1</span><span class="p">];</span>
<span class="o">^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span>
<span class="mi">3</span><span class="n">rdparty</span><span class="o">/</span><span class="n">edbee</span><span class="o">-</span><span class="n">lib</span><span class="o">/</span><span class="n">vendor</span><span class="o">/</span><span class="n">onig</span><span class="o">/</span><span class="n">config</span><span class="p">.</span><span class="n">h</span><span class="o">:</span><span class="mi">109</span><span class="o">:</span><span class="mi">22</span><span class="o">:</span> <span class="n">note</span><span class="o">:</span> <span class="n">expanded</span> <span class="n">from</span> <span class="n">macro</span> <span class="err">'</span><span class="n">SIZEOF_VOIDP</span><span class="err">'</span>
<span class="cp">#define SIZEOF_VOIDP 8
</span> <span class="o">^</span>
<span class="mi">1</span> <span class="n">error</span> <span class="n">generated</span><span class="p">.</span>
<span class="n">shared</span><span class="o">:</span><span class="n">ERROR</span><span class="o">:</span> <span class="n">compiler</span> <span class="n">frontend</span> <span class="n">failed</span> <span class="n">to</span> <span class="n">generate</span> <span class="n">LLVM</span> <span class="n">bitcode</span><span class="p">,</span> <span class="n">halting</span>
<span class="n">Makefile</span><span class="o">:</span><span class="mi">36871</span><span class="o">:</span> <span class="n">recipe</span> <span class="k">for</span> <span class="n">target</span> <span class="err">'</span><span class="n">regcomp</span><span class="p">.</span><span class="n">o</span><span class="err">'</span> <span class="n">failed</span>
</code></pre>
<p>Both sizeof are set to 8:</p>
<pre><code class="c syntaxhl" data-language="c"><span class="n">onig</span><span class="err">$</span> <span class="n">cat</span> <span class="n">config</span><span class="p">.</span><span class="n">h</span> <span class="o">|</span> <span class="n">grep</span> <span class="n">SIZEOF_LONG</span>
<span class="cp">#define SIZEOF_LONG 8
#define SIZEOF_LONG_LONG 8
</span></code></pre>
<p>Is there a way to fix this issue or add a workaround for emscripten (<code>__EMSCRIPTEN__</code>)?</p> Ruby master - Feature #16012 (Assigned): Add a (small) test-install suite?https://redmine.ruby-lang.org/issues/160122019-07-19T14:27:56ZMSP-Greg (Greg L)
<p>At various times there has been discussion about whether testing should require <code>make install</code>. Although I prefer to do testing using install (vs build), I see it as a choice, and not a requirement.</p>
<p>From time to time various issues have arisen that cannot be found with 'build' testing. Often, these issues cause CI test failure with master/trunk/ruby-head in external repos. Sometimes people blame 'Core', other times Travis, or rvm. Regardless, it doesn't look good.</p>
<p>So, might a small set of tests that check install functionality be added? It may need to be two separate (but equivalent) scripts. One for *nix, one for Windows.</p>
<p>In ruby-loco, I'm using a ps1 script to check that CLI bin files work. As soon as the update is pushed here, I'll add a test for nested bundler commands...</p> Ruby master - Feature #15939 (Assigned): Dump symbols reference to their fstr in ObjectSpace.dump()https://redmine.ruby-lang.org/issues/159392019-06-19T12:52:38Zbyroot (Jean Boussier)byroot@ruby-lang.org
<p>Patch: <a href="https://github.com/ruby/ruby/pull/2240" class="external">https://github.com/ruby/ruby/pull/2240</a></p>
<p>Symbols wether they are dynamic or static do hold a reference onto their respective fstring, so it's important to dump these references so that it's possible to see that a String isn't garbage collected because it has an associated Symbol.</p>
<p>Dumping a static Symbol (before):</p>
<pre><code>>> puts ObjectSpace.dump(:foobar)
{"type":"SYMBOL", "value":"foobar"}
</code></pre>
<p>after:</p>
<pre><code>>> puts ObjectSpace.dump(:foobar)
{"address":"0x7a210c", "type":"SYMBOL", "value":"foobar", "references":["0x7f8dd482c7d8"], "dynamic": false}
</code></pre>
<p>Dumping a dynamic Symbol (before):</p>
<pre><code>>> puts ObjectSpace.dump("foobar".to_sym)
{"address":"0x7fcdf7042eb0", "type":"SYMBOL", "class":"0x7fcdf70c8628", "frozen":true, "bytesize":6, "value":"foobar", "memsize":40, "flags":{"wb_protected":true}}
</code></pre>
<p>After:</p>
<pre><code>>> puts ObjectSpace.dump("foobar".to_sym)
{"address":"0x7fcdf7042eb0", "type":"SYMBOL", "class":"0x7fcdf70c8628", "frozen":true, "bytesize":6, "value":"foobar", "dynamic":true, "references":["0x7fcdf7042ed8"], "memsize":40, "flags":{"wb_protected":true}}
</code></pre>
<p>Limitations:</p>
<p><code>ObjectSpace.dump_all</code> rely on <code>rb_objspace_reachable_objects_from</code> to list an object's references.<br>
Because of this static symbol "references" are not followed, and as such are invisible in <code>ObjectSpace.dump_all</code>.</p>
<p>I'd like to correct it but it's quite more complicated because <code>rb_objspace_reachable_objects_from</code> is used by the GC, so I'd need to duplicate that function for <code>objspace_dump</code> usage.</p>
<p>So I wouldn't mind some opinion on that before attempting it.</p> Ruby master - Feature #15878 (Assigned): Make exit faster by not running GChttps://redmine.ruby-lang.org/issues/158782019-05-26T19:13:02Zgrosser (Michael Grosser)michael@grosser.it
<p>I noticed that exit takes 0.2 ... I'm trying to write a fast cli, so any improvement here would be great or an option to opt-out of certain cleanup tasks<br>
exit! takes a constant low time</p>
<pre><code>ruby -rbenchmark -e 'puts Benchmark.realtime { Process.wait(fork { exit }) }' # 0.03 great!
ruby -rbenchmark -rrubocop -e 'puts Benchmark.realtime { Process.wait(fork { exit }) }' # 0.18 :(
ruby -rbenchmark -rrubocop -e 'GC.disable; puts Benchmark.realtime { Process.wait(fork { exit }) }' # 0.04 :D
ruby -rbenchmark -rrubocop -e 'puts Benchmark.realtime { Process.wait(fork { exit! }) }' # 0.002 ... fast but unsafe
</code></pre> Ruby master - Misc #15806 (Assigned): Explicitly initialise encodings on init to remove branches ...https://redmine.ruby-lang.org/issues/158062019-04-27T23:41:34Zmethodmissing (Lourens Naudé)lourens@bearmetal.eu
<p>References Github PR <a href="https://github.com/ruby/ruby/pull/2128" class="external">https://github.com/ruby/ruby/pull/2128</a></p>
<p>I noticed that the encoding table is loaded on startup of even just <code>miniruby</code> (minimal viable interpreter use case) through this backtrace during ruby setup:</p>
<pre><code>/home/lourens/src/ruby/ruby/miniruby(rb_enc_init+0x12) [0x56197b0c0c72] encoding.c:587
/home/lourens/src/ruby/ruby/miniruby(rb_usascii_encoding+0x1a) [0x56197b0c948a] encoding.c:1357
/home/lourens/src/ruby/ruby/miniruby(Init_sym+0x7a) [0x56197b24810a] symbol.c:42
/home/lourens/src/ruby/ruby/miniruby(rb_call_inits+0x1d) [0x56197b11afed] inits.c:25
/home/lourens/src/ruby/ruby/miniruby(ruby_setup+0xf6) [0x56197b0ec9d6] eval.c:74
/home/lourens/src/ruby/ruby/miniruby(ruby_init+0x9) [0x56197b0eca39] eval.c:91
/home/lourens/src/ruby/ruby/miniruby(main+0x5a) [0x56197b051a2a] ./main.c:41
</code></pre>
<p>Therefore I think it makes sense to instead initialize encodings explicitly just prior to symbol init, which is the first entry point into the interpreter loading that currently triggers <code>rb_enc_init</code> and remove the initialization check branches from the various lookup methods.</p>
<p>Some of the branches collapsed, <code>cachegrind</code> output, columns are <code>Ir Bc Bcm Bi Bim</code> with <code>Ir</code> (instructions retired), <code>Bc</code> (branches taken) and <code>Bcm</code> (branches missed) relevant here as there are no indirect branches (function pointers etc.):</p>
<p>(hot function, many instructions retired and branches taken and missed)</p>
<pre><code> . . . . . rb_encoding *
. . . . . rb_enc_from_index(int index)
835,669 0 0 0 0 {
13,133,536 6,337,652 50,267 0 0 if (!enc_table.list) {
3 0 0 0 0 rb_enc_init();
. . . . . }
23,499,349 8,006,202 293,161 0 0 if (index < 0 || enc_table.count <= (index &= ENC_INDEX_MASK)) {
. . . . . return 0;
. . . . . }
30,024,494 0 0 0 0 return enc_table.list[index].enc;
1,671,338 0 0 0 0 }
</code></pre>
<p>(cold function, representative of the utf8 variant more or less too)</p>
<pre><code> . . . . . rb_encoding *
. . . . . rb_ascii8bit_encoding(void)
. . . . . {
27,702 9,235 955 0 0 if (!enc_table.list) {
. . . . . rb_enc_init();
. . . . . }
9,238 0 0 0 0 return enc_table.list[ENCINDEX_ASCII].enc;
9,232 0 0 0 0 }
</code></pre>
<p>I think lazy loading encodings and populating the table is fine, but initializing it can be done more explicitly in the boot process.</p> Ruby master - Feature #15628 (Assigned): init_inetsock_internal should fallback to IPv4 if IPv6 i...https://redmine.ruby-lang.org/issues/156282019-02-28T11:51:17Zsonalkr132 (Aditya Prakash)
<p>Hi,</p>
<p>This is not really bug but more of a missing feature. Let me layout steps to reproduce what I am trying to achieve:</p>
<ul>
<li>Add local entries for <code>example.com</code>
</li>
</ul>
<pre><code>$ echo "::1 example.com www.example.com
127.0.0.1 example.com www.example.com" | sudo tee --append /etc/hosts
</code></pre>
<ul>
<li>Add rule to <code>DROP</code> ipv6 packets: <code>sudo ip6tables -P INPUT DROP</code>
</li>
<li>Start a server: <code>ruby -rwebrick -e 'WEBrick::HTTPServer.new(Port: 8000).start'</code>
</li>
<li>Making request using Net:HTTP with timeout (<code>Net::OpenTimeout</code>) after after 60 seconds: <code>ruby -rnet/http -e "Net::HTTP.get(URI('http://example.com:8000'))"</code>
</li>
</ul>
<p>As far as I understand, <a href="https://github.com/ruby/ruby/blob/4444025d16ae1a586eee6a0ac9bdd09e33833f3c/ext/socket/ipsocket.c#L42" class="external">init_inetsock_internal</a> needs to fallback to ipv4 for Net::HTTP.get to work. IPv6 route being broke is expected and hence, <a href="https://tools.ietf.org/html/rfc8305" class="external">RFC8305</a> recommends fallback to IPv4.<br>
Support for IPv6 fallback is spotty across languages and http clients, for example, <a href="https://github.com/golang/go/blob/master/src/net/dial.go#L47" class="external">golang supports it</a> but python doesn't, making request with <code>curl</code> works but <code>wget</code> hangs.</p> Ruby master - Bug #15550 (Assigned): Windows - gem bin files - can't run from bash shellhttps://redmine.ruby-lang.org/issues/155502019-01-20T00:45:45ZMSP-Greg (Greg L)
<p>As I recall, ruby-loco is no longer touching the gem related files located in the bin folder. Previously, there were two files associated with each gem, one with a .cmd/.bat extension, one without.</p>
<p>Currently, there is just one file with a .cmd extension. I have seen this before, and just came across it again, where gems are using *nix scripts run with either the MSYS2 shell or the Git shell in their CI. Hence, there is an expectation for the plain (extensionless) file to exist.</p>
<p>Not sure if this is considered a breaking change or a bug/issue.</p>
<p>Thanks, Greg</p> Ruby master - Bug #15499 (Assigned): Breaking behavior on ruby 2.6: rb_thread_call_without_gvl do...https://redmine.ruby-lang.org/issues/154992019-01-03T01:37:49Zapolcyn (alex polcyn)
<p>This issue was noticed when trying to add ruby 2.6 support to the "grpc" ruby gem (this gem is a native C-extension), and was caught by a unit test.</p>
<p>There are several APIs on the grpc ruby gem (<a href="https://github.com/grpc/grpc/tree/master/src/ruby" class="external">https://github.com/grpc/grpc/tree/master/src/ruby</a>) that invoke "rb_thread_call_without_gvl" on the current thread, doing a blocking operation in the "without gvl" callback and cancel that blocking operation in the "unblocking function". These APIs work in ruby versions prior to ruby 2.6 (e.g. ruby 2.5), but have problems when used on ruby 2.6</p>
<p>Minimal repro:</p>
<p>My system:</p>
<pre><code>> lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 9.6 (stretch)
Release: 9.6
Codename: stretch
> ruby -v
ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-linux
# I installed ruby 2.6.0 with rvm - https://rvm.io/rvm/install
> GRPC_CONFIG=dbg gem install grpc --platform ruby # build grpc gem from source with debug symbols
</code></pre>
<p>ruby script, "repro.rb" that looks like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'grpc'</span>
<span class="n">ch</span> <span class="o">=</span> <span class="no">GRPC</span><span class="o">::</span><span class="no">Core</span><span class="o">::</span><span class="no">Channel</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'localhost:1234'</span><span class="p">,</span> <span class="p">{},</span> <span class="ss">:this_channel_is_insecure</span><span class="p">)</span>
<span class="n">ch</span><span class="p">.</span><span class="nf">watch_connectivity_state</span><span class="p">(</span><span class="n">ch</span><span class="p">.</span><span class="nf">connectivity_state</span><span class="p">,</span> <span class="no">Time</span><span class="p">.</span><span class="nf">now</span> <span class="o">+</span> <span class="mi">360</span><span class="p">)</span>
</code></pre>
<p>Run "ruby repro.rb" with an interactive shell, and it will hang there. At this point, ctrl^C the process, and it will not terminate.<br>
What should happen is this unblocking func should be invoked: <a href="https://github.com/grpc/grpc/blob/master/src/ruby/ext/grpc/rb_channel.c#L354" class="external">https://github.com/grpc/grpc/blob/master/src/ruby/ext/grpc/rb_channel.c#L354</a>, but as seen with logging or debuggers, that unblocking func is never ran. Thus the blocking operation never completes and the main thread is stuck.</p>
<p>When the same repro.rb is ran on e.g. ruby 2.5.3 or ruby 2.4.1, the blocking operation is unblocked and the process terminates, as expected, when sending it a SIGINT.</p>
<p>Also note that if the blocking operation is put in a background thread, e.g. with this script:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'grpc'</span>
<span class="n">th</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">ch</span> <span class="o">=</span> <span class="no">GRPC</span><span class="o">::</span><span class="no">Core</span><span class="o">::</span><span class="no">Channel</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'localhost:1234'</span><span class="p">,</span> <span class="p">{},</span> <span class="ss">:this_channel_is_insecure</span><span class="p">)</span>
<span class="n">ch</span><span class="p">.</span><span class="nf">watch_connectivity_state</span><span class="p">(</span><span class="n">ch</span><span class="p">.</span><span class="nf">connectivity_state</span><span class="p">,</span> <span class="no">Time</span><span class="p">.</span><span class="nf">now</span> <span class="o">+</span> <span class="mi">360</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">th</span><span class="p">.</span><span class="nf">join</span>
</code></pre>
<p>then "unblocking" functions will in fact be invoked upon sending the process a SIGINT, so this looks like a problem specifically with rb_thread_call_without_gvl being used on the main thread.</p>
<p>Please let me know and I can provide more details or alternative repro cases.</p>
<p>Thanks in advance.</p> Ruby master - Misc #15487 (Assigned): Clarify default gems maintanance policyhttps://redmine.ruby-lang.org/issues/154872018-12-29T12:30:23Zzverok (Victor Shepelev)zverok.offline@gmail.com
<p>In addition to <a class="issue tracker-5 status-7 priority-4 priority-default closed" title="Misc: Default gems README.md (Feedback)" href="https://redmine.ruby-lang.org/issues/15486">#15486</a>, I'd like to raise the question of the general <em>maintanance policy</em> for "default" Ruby gems, in particular:</p>
<ul>
<li>who is responsible for each gem and how they should be contacted?</li>
<li>what are goals and policies for gems code quality and documentation?</li>
<li>where do default gems are discussed?</li>
<li>what are some promises/guarantees default gems maintainers try to fulfill?</li>
</ul>
<p>The most demonstrative example I'd like to point is <code>json</code> gem:</p>
<ul>
<li>The source at <a href="https://github.com/ruby/json" class="external">ruby/json</a> is NOT authoritative as far as I can tell, the authoritative one is <a href="https://github.com/flori/json" class="external">flori/json</a>
</li>
<li>The gem still holds signs of the times it was independent (<code>Pure</code> and <code>Ext</code> JSON implementations, but <code>Pure</code> is not copied into the <code>ruby/lib</code> on releases, rendering standard docs pretty weird), and has NO mention it is THE json gem of Ruby</li>
<li>The gem seems unmaintained, considering the amount of <a href="https://github.com/flori/json/pulls" class="external">PRs</a> and <a href="https://github.com/flori/json/issues" class="external">issues</a>, lot of them without any reaction for months</li>
<li>When I tried to update JSON docs, in <a href="https://bugs.ruby-lang.org/issues/14581" class="external">core tracker issue</a> I was asked to make a PR to "upstream repository", but there, the PRs (<a href="https://github.com/flori/json/pull/347" class="external">#347</a>, <a href="https://github.com/flori/json/pull/349" class="external">#349</a>) was simply ignored; Ruby 2.6 was released without new docs, despite the fact PRs were made at <strong>March</strong> and require almost no code review (unlike even some promising optimization PRs, that were also hanging there since Feb/Mar)</li>
</ul>
<p>It is just one unfortunate case (TBH, my experience with contributing to other libraries, like <code>csv</code> and <code>psych</code> was much smoother), but it demonstrates some common lack of transparency in maintaining of Ruby's standard library</p> Ruby master - Feature #15281 (Assigned): Speed up Set#intersect with size check.https://redmine.ruby-lang.org/issues/152812018-11-03T13:08:32ZRGBD (Oleg Zubchenko)
<p>Current implementation computes set intersection s1 & s2 in O(s2.size) time.<br>
It can be reduced to O([s1.size, s2.size].min) time.</p>
<p>Additional speedup comes from using #each instead of #do_with_enum.</p>
<p>See files attached for benchmarks.</p>
<p><a href="https://github.com/ruby/ruby/pull/2003" class="external">Pull Request</a></p>
<p>P.S. using benchmark-ips gem</p> Ruby master - Feature #15239 (Assigned): [patch] test-spec win32olehttps://redmine.ruby-lang.org/issues/152392018-10-20T19:32:07ZMSP-Greg (Greg L)
<p>Some of the current Win32OLE spec tests use the InternetExplorer control. This control is not available on Azure pipelines. Attached patch changes to use the MSXML control, adds a guard for it, and also does some refactoring to lower requires when not run under Windows, etc. Also, since the MSXML object is quite a bit 'smaller' than InternetExplorer, tests run faster.</p>
<p>Passed in my fork at <a href="https://ci.appveyor.com/project/MSP-Greg/ruby/builds/19663145" class="external">https://ci.appveyor.com/project/MSP-Greg/ruby/builds/19663145</a></p>
<p>Note also that since there have been recent commits stabilizing the spec suite, the above build job changed the mswin spec tests to run parallel, and they passed. The change from serial to parallel is not included in the patches. It is a separate commit in the branch on my fork.</p>
<p>GitHub patch is at:<br>
<a href="https://github.com/MSP-Greg/ruby/commit/d1daf9a66f491abfac5e84a50f152505baa1ccac.patch" class="external">https://github.com/MSP-Greg/ruby/commit/d1daf9a66f491abfac5e84a50f152505baa1ccac.patch</a></p> Ruby master - Feature #15166 (Assigned): 2.5 times faster implementation than current gcd implmen...https://redmine.ruby-lang.org/issues/151662018-09-26T18:30:29Zjzakiya (Jabari Zakiya)
<p>This is to be more explicit (and accurate) than <a href="https://bugs.ruby-lang.org/issues/15161" class="external">https://bugs.ruby-lang.org/issues/15161</a></p>
<p>This is my modified gcd benchmarks code, originally presented by Daniel Lemire (see 15161).</p>
<p><a href="https://gist.github.com/jzakiya/44eae4feeda8f6b048e19ff41a0c6566" class="external">https://gist.github.com/jzakiya/44eae4feeda8f6b048e19ff41a0c6566</a></p>
<p>Ruby's current implementation of Stein's gcd algorithm is only slightly faster than the<br>
code posted on the wikepedia page, and over 2.5 times slower than the fastest implementation<br>
in the benchmarks.</p>
<pre><code>[jzakiya@localhost ~]$ ./gcdbenchmarks
gcd between numbers in [1 and 2000]
gcdwikipedia7fast32 : time = 99
gcdwikipedia4fast : time = 121
gcdFranke : time = 126
gcdwikipedia3fast : time = 134
gcdwikipedia2fastswap : time = 136
gcdwikipedia5fast : time = 139
gcdwikipedia7fast : time = 138
gcdwikipedia2fast : time = 136
gcdwikipedia6fastxchg : time = 144
gcdwikipedia2fastxchg : time = 156
gcd_iterative_mod : time = 210
gcd_recursive : time = 215
basicgcd : time = 211
rubygcd : time = 267
gcdwikipedia2 : time = 321
gcd between numbers in [1000000001 and 1000002000]
gcdwikipedia7fast32 : time = 100
gcdwikipedia4fast : time = 121
gcdFranke : time = 126
gcdwikipedia3fast : time = 134
gcdwikipedia2fastswap : time = 136
gcdwikipedia5fast : time = 138
gcdwikipedia7fast : time = 138
gcdwikipedia2fast : time = 136
gcdwikipedia6fastxchg : time = 144
gcdwikipedia2fastxchg : time = 156
gcd_iterative_mod : time = 210
gcd_recursive : time = 215
basicgcd : time = 211
rubygcd : time = 269
gcdwikipedia2 : time = 323
</code></pre>
<p>This is Ruby's code per: <a href="https://github.com/ruby/ruby/blob/3abbaab1a7a97d18f481164c7dc48749b86d7f39/rational.c#L285-L307" class="external">https://github.com/ruby/ruby/blob/3abbaab1a7a97d18f481164c7dc48749b86d7f39/rational.c#L285-L307</a><br>
which is basically the wikepedia implementation.</p>
<pre><code>inline static long
i_gcd(long x, long y)
{
unsigned long u, v, t;
int shift;
if (x < 0)
x = -x;
if (y < 0)
y = -y;
if (x == 0)
return y;
if (y == 0)
return x;
u = (unsigned long)x;
v = (unsigned long)y;
for (shift = 0; ((u | v) & 1) == 0; ++shift) {
u >>= 1;
v >>= 1;
}
while ((u & 1) == 0)
u >>= 1;
do {
while ((v & 1) == 0)
v >>= 1;
if (u > v) {
t = v;
v = u;
u = t;
}
v = v - u;
} while (v != 0);
return (long)(u << shift);
}
</code></pre>
<p>This is the fastest implementation from the benchmarks. (I originally, wrongly, cited<br>
the implementation in the article, which is 4|5th fastest in benchmarks, but<br>
still almost 2x faster than the Ruby implementation.)</p>
<pre><code>// based on wikipedia's article,
// fixed by D. Lemire, K. Willets
unsigned int gcdwikipedia7fast32(unsigned int u, unsigned int v)
{
int shift, uz, vz;
if ( u == 0) return v;
if ( v == 0) return u;
uz = __builtin_ctz(u);
vz = __builtin_ctz(v);
shift = uz > vz ? vz : uz;
u >>= uz;
do {
v >>= vz;
int diff = v;
diff -= u;
if ( diff == 0 ) break;
vz = __builtin_ctz(diff);
if ( v < u ) u = v;
v = abs(diff);
} while( 1 );
return u << shift;
}
</code></pre>
<p>The key to speeding up all the algorithms is using the <code>__builtin_ctz(x)</code> directive<br>
to determine the number of trailing binary '0's.</p> Ruby master - Misc #14917 (Assigned): Add RDoc documents to tar ballhttps://redmine.ruby-lang.org/issues/149172018-07-18T04:08:50Zaycabta (aycabta .)aycabta@gmail.com
<p>I guess that distribution packages should include RDoc documents' files because RDoc documents installation step needs too long time.</p>
<p>There is the other reason. RDoc sometimes fails during "generating RDoc documentation" phase of installation.</p>
<p>Some case examples:</p>
<ul>
<li><a href="https://bugs.ruby-lang.org/issues/11494" class="external">https://bugs.ruby-lang.org/issues/11494</a></li>
<li><a href="https://bugs.ruby-lang.org/issues/14663" class="external">https://bugs.ruby-lang.org/issues/14663</a></li>
<li><a href="https://bugs.ruby-lang.org/issues/14874" class="external">https://bugs.ruby-lang.org/issues/14874</a></li>
<li><a href="https://bugs.ruby-lang.org/issues/11514" class="external">https://bugs.ruby-lang.org/issues/11514</a></li>
</ul>
<p>Maybe, generating RDoc documentation is so heavy task for low memory situation, and other tasks are lighter than it.</p> Ruby master - Feature #14901 (Assigned): [PATCH] do not block SIGCHLD in normal Ruby Threadshttps://redmine.ruby-lang.org/issues/149012018-07-08T02:53:23Znormalperson (Eric Wong)normalperson@yhbt.net
<p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/10073">@k0kubun (Takashi Kokubun)</a>: any opinions on this? Thanks.</p>
<pre><code>I blocked SIGCHLD in normal Ruby Threads for [Bug #14867]
because I noticed at least two places which could not deal
with spurious wakeups in our test suite.
I also want to get rid of timer-thread due to resource
limitations <a href="https://blade.ruby-lang.org/ruby-core/87773">[ruby-core:87773]</a>. MJIT causes many SIGCHLD signals
so I found the following problems with cppflags=-DMJIT_FORCE_ENABLE=1
* OpenSSL::PKey::*.new does not resume on handle signals.
rhenium acknowledged the problem and it should be in trunk soon:
https://bugs.ruby-lang.org/issues/14882
* test/-ext-/gvl/test_last_thread.rb does not handle spurious
wakeups. Original report is in Japanese:
https://bugs.ruby-lang.org/issues/11237
I don't think it's a realistic expectation for code to be
unable to deal with spurious wakeups.
One alternative could be to handle signals with MJIT thread
when MJIT is enabled, or to lazy-spawn timer thread to handle
signals when MJIT is enabled (MJIT + gcc requires a lot of
resources, anyways).
</code></pre> Ruby master - Feature #14737 (Assigned): Split default gems into separate directory structurehttps://redmine.ruby-lang.org/issues/147372018-05-04T10:38:57Zvo.x (Vit Ondruch)v.ondruch@tiscali.cz
<p>On Fedora, we are using operating_system.rb <a href="https://src.fedoraproject.org/rpms/ruby/blob/master/f/operating_system.rb" class="external">1</a>, <a href="https://src.fedoraproject.org/rpms/ruby/blob/f27/f/operating_system.rb" class="external">2</a> to setup various RubyGems paths. Unfortunately, if we change Gem.default_dir (which we want to point into user home directory on Fedora), then this also changes location for default gems (!!), which are later not discovered by RubyGems <a href="https://lists.fedoraproject.org/archives/list/ruby-sig@lists.fedoraproject.org/message/RZUUKFMNKRB6TGKCQT3FLZYANP5WLEKN/" class="external">3</a>. It was not been a big deal for use, since we used to unbundle the gems shipped in Ruby, but with the gemification of StdLib, unbundlig becomes unsustainable (it is more work, but mainly it is incompatible change).</p>
<p>To fix this issue, I modified the operating_system.rb to behave similarly to what Arch does <a href="https://wiki.archlinux.org/index.php/ruby" class="external">4</a>, i.e. we started to inject "--user-install" option <a href="https://src.fedoraproject.org/rpms/ruby/blob/master/f/operating_system.rb" class="external">1</a>. Unfortunately, this revealed the RubyGems are not respecting their own interfaces and I had to fix at least one of them along the way to make it work <a href="https://github.com/rubygems/rubygems/pull/2116" class="external">6</a>. Apparently, using the "--user-install" option itself has some drawbacks and what is worse, it is not respected by Bundler, which was recently pointed out <a href="https://bugzilla.redhat.com/show_bug.cgi?id=1574594" class="external">5</a>.</p>
<p>When I was fixing RubyGems <a href="https://github.com/rubygems/rubygems/pull/2116" class="external">6</a>, I just realized how the default gems are hacked up and how much is the original RubyGems configurability broken by this. This leads me to the proposal: <strong>Could we please install default gems into different directory then the other, user installed, gems?</strong> Since RubyGems were always designed to support various gem directory structures, the directory structure for default gems would become just other directory directory structure and would not collide with overrides in operating_system.rb, letting the distributions to override what was always designed to be overridable.</p>
<p>BTW I believe that one nice side effect of this change would be simplification of RubyGems code base. The default gems would live in "default_gems" directory, their .gemspec files could be in standard "default_gems/specifications" directory and we could forget about "default_gems/specifications/defaults", etc.</p>
<p>BTW2 I could fill this against RubyGems, but the default gems are Ruby stuff IMO, so I think this is appropriate tracker.</p> Ruby master - Bug #14727 (Assigned): TestQueue#test_queue_with_trap always timeout on Windows10https://redmine.ruby-lang.org/issues/147272018-05-01T02:27:47Zusa (Usaku NAKAMURA)usa@garbagecollect.jp
<p>表題の通りです。ささださんも把握しているそうなので、備忘録として。</p>
<pre><code>[19/35] TestQueue#test_queue_with_trap = 10.13 s
1) Error:
TestQueue#test_queue_with_trap:
Timeout::Error: execution of assert_in_out_err expired timeout (10 sec)
pid 11608 exit 0
|
C:/Users/usa/develop/ruby/core/mytree/test/thread/test_queue.rb:553:in `test_queue_with_trap'
</code></pre> Ruby master - Feature #14476 (Assigned): Adding same_all? for checking whether all items in an Ar...https://redmine.ruby-lang.org/issues/144762018-02-14T15:41:30Zmrkn (Kenta Murata)muraken@gmail.com
<p>In this issue, I propose to introduce <code>same_all?</code> instance method of <code>Array</code> class. This new method checks whether all items in the receiver are the same.</p>
<p>Today, I needed to write a code to judge whether all items in an <code>Array</code> are the same. I wanted to make the following expression, which I've written first, more efficient.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">ary</span><span class="p">.</span><span class="nf">all?</span> <span class="p">{</span><span class="o">|</span><span class="n">e</span><span class="o">|</span> <span class="n">e</span><span class="p">.</span><span class="nf">foo</span> <span class="o">==</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">foo</span> <span class="p">}</span>
</code></pre>
<p>I considered about the following simpler case, too.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">ary</span><span class="p">.</span><span class="nf">all?</span> <span class="p">{</span><span class="o">|</span><span class="n">e</span><span class="o">|</span> <span class="n">e</span> <span class="o">==</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="p">}</span>
</code></pre>
<p>As I discussed with some CRuby committers and my colleagues at Speee, Inc., I found that both cases can be written more efficiently as follows:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># for the 1st case</span>
<span class="n">ary</span><span class="p">.</span><span class="nf">empty?</span> <span class="o">||</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">foo</span><span class="p">.</span><span class="nf">yield_self</span> <span class="p">{</span><span class="o">|</span><span class="n">e0</span><span class="o">|</span> <span class="n">ary</span><span class="p">[</span><span class="mi">1</span><span class="o">..-</span><span class="mi">1</span><span class="p">].</span><span class="nf">all?</span> <span class="p">{</span><span class="o">|</span><span class="n">e</span><span class="o">|</span> <span class="n">e</span><span class="p">.</span><span class="nf">foo</span> <span class="o">==</span> <span class="n">e0</span> <span class="p">}</span> <span class="p">}</span><span class="err"> </span>
<span class="c1"># for the 2nd case</span>
<span class="n">ary</span><span class="p">.</span><span class="nf">empty?</span> <span class="o">||</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="o">..-</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="n">ary</span><span class="p">[</span><span class="mi">1</span><span class="o">..-</span><span class="mi">1</span><span class="p">]</span>
</code></pre>
<p>However, it is not easy to understand the intent of either expression, which is to check whether all items are the same.</p>
<p>I want to give this feature a clear name to make code readable. And I think it should be provided as a core feature because it can be made more efficient by being implemented in C language.</p>
<p>The benchmark script is: <a href="https://gist.github.com/mrkn/26a0fcfc431a45fe809fbbef95aceaf5" class="external">https://gist.github.com/mrkn/26a0fcfc431a45fe809fbbef95aceaf5</a><br>
I used it to find the efficient expressions. The example result of this benchmark on my MacBook Pro is here.</p>
<pre><code>$ ruby -v bench.rb
ruby 2.6.0dev (2018-02-14 trunk 62402) [x86_64-darwin16]
----------------------------------------
Benchmark case: shuffle
user system total real
all?-method-1 0.001525 0.000088 0.001613 ( 0.001632)
all?-method-2 0.000489 0.000031 0.000520 ( 0.000565)
all?-method-3 0.000444 0.000039 0.000483 ( 0.000482)
all?-item 0.000325 0.000078 0.000403 ( 0.000402)
opt-method 0.655959 0.033814 0.689773 ( 0.708515)
opt-item 0.000316 0.000001 0.000317 ( 0.000317)
----------------------------------------
Benchmark case: tail0
user system total real
all?-method-1 9.412810 0.231126 9.643936 ( 9.681118)
all?-method-2 5.375075 0.137908 5.512983 ( 5.754550)
all?-method-3 5.226132 0.167640 5.393772 ( 5.507031)
all?-item 0.873700 0.007545 0.881245 ( 0.917210)
opt-method 5.319648 0.172547 5.492195 ( 5.633140)
opt-item 0.174349 0.001974 0.176323 ( 0.183002)
----------------------------------------
Benchmark case: head0
user system total real
all?-method-1 0.002421 0.000068 0.002489 ( 0.002489)
all?-method-2 0.002169 0.000213 0.002382 ( 0.002382)
all?-method-3 0.001624 0.000026 0.001650 ( 0.001651)
all?-item 0.000623 0.000001 0.000624 ( 0.000624)
opt-method 4.779120 0.146312 4.925432 ( 4.951167)
opt-item 0.000629 0.000001 0.000630 ( 0.000629)
----------------------------------------
Benchmark case: all1
user system total real
all?-method-1 9.379650 0.255865 9.635515 ( 9.683078)
all?-method-2 4.950280 0.150659 5.100939 ( 5.140174)
all?-method-3 4.857898 0.129125 4.987023 ( 5.003142)
all?-item 0.694113 0.001295 0.695408 ( 0.702370)
opt-method 5.032373 0.121708 5.154081 ( 5.189599)
opt-item 0.170540 0.002069 0.172609 ( 0.180343)
</code></pre> Ruby master - Feature #14412 (Assigned): DRb UNIX on local machine: add support for getpeereid()https://redmine.ruby-lang.org/issues/144122018-01-27T17:26:32ZAnonymous
<p>Hi,</p>
<p><code>UNIXSocket</code> has this method <code>#getpeereid()</code> which returns effective user ID and effective group ID.</p>
<p>DRb using <code>drbunix://</code> on local machine doesn't support that method. In my use case, I need to verify clients via that method. So it would be great if you add support to DRb.</p>
<p>Actually that method <code>#getpeereid()</code> is from <code>BaseSocket</code>, but documentation states that it only supports UNIX sockets. I mean, it's a general method from parent class. So you can do the same with DRb: add some similar method, but only works via <code>drbunix://</code> on local machine. Otherwise you can raise error...</p>
<p>Thank you,</p> Ruby master - Feature #14397 (Assigned): public, protected and private should return their argume...https://redmine.ruby-lang.org/issues/143972018-01-24T21:27:26Zusa (Usaku NAKAMURA)usa@garbagecollect.jp
<p>Matsuda-san suggested me that <code>public</code>, <code>protected</code> and <code>private</code> should return their arguments instead of <code>self</code>,<br>
to write such code:`</p>
<pre><code class="Ruby syntaxhl" data-language="Ruby"><span class="nb">require</span> <span class="s2">"finalist"</span>
<span class="c1"># see https://github.com/joker1007/finalist</span>
<span class="k">class</span> <span class="nc">Foo</span>
<span class="kp">extend</span> <span class="no">Finalist</span>
<span class="n">final</span> <span class="kp">private</span> <span class="k">def</span> <span class="nf">foo</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>I believe that it's reasonable request, and also believe that there is no product code which uses the return values of <code>public</code>, <code>protected</code> and <code>private</code>.<br>
Matz, how do you think about this change?<br>
The patch is attached.</p> 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 - Bug #13999 (Assigned): Cygwin 環境で ripper_state_lex.rb がコアダンプするhttps://redmine.ruby-lang.org/issues/139992017-10-11T05:19:02Zhigaki (masaru higaki)mas.higa@gmail.com
<p>いくつかの gem をインストールした際にコアダンプしました。</p>
<p>--no-ri を付けるとコアダンプしないことから ri の何かが関係していそうです。</p>
<p>$ gem install bitclust-core # コアダンプ<br>
$ gem install --no-ri bitclust-core # コアダンプしない</p>
<p>標準出力、エラー出力を添付します。</p> Ruby master - Feature #13847 (Assigned): Gem activated problem for default gemshttps://redmine.ruby-lang.org/issues/138472017-08-29T08:53:45Zhsbt (Hiroshi SHIBATA)hsbt@ruby-lang.org
<p>If you try to use some default gems with a fixed version using Bundler, there are cases where the current RubyGems/Bundler/Ruby specification can not be used with the version specified by the user.</p>
<p>For example</p>
<pre><code>$ ruby -v
ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin17]
$ gem list | grep openssl
openssl (2.0.5, 2.0.4, default: 2.0.3)
</code></pre>
<p>In the environment such as <code>require 'openssl'</code>, the version that is activated when openssl is searched with openssl is the version found first, ie 2.0.5.</p>
<pre><code>$ ruby -ropenssl -e 'p OpenSSL::VERSION'
"2.0.5"
</code></pre>
<p>At this time, for example, suppose the user really wants to use openssl 2.0.4 and wrote the following Gemfile.</p>
<pre><code>> cat Gemfile
# frozen_string_literal: true
source "https://rubygems.org"
gem 'openssl', '2.0.4'
</code></pre>
<p>Unfortunately, since rubygems has required openssl before the bundler runs it will result in an activated error like this:</p>
<pre><code>> bundle exec ruby -ropenssl -e 'p OpenSSL::VERSION'
/path/to/2.4.1/lib/ruby/gems/2.4.0/gems/bundler-1.15.4/lib/bundler/runtime.rb:317:in `check_for_activated_spec!': You have already activated openssl 2.0.5, but your Gemfile requires openssl 2.0.4. Prepending `bundle exec` to your command may solve this. (Gem::LoadError)
</code></pre>
<p>This problem can be avoided by bundling it as a vendoring library under bundler's repository if it is a default gem implemented with pure ruby.</p>
<p><a href="Https://github.com/bundler/bundler/blob/master/lib/bundler/vendor/fileutils/lib/fileutils.rb" class="external">Https://github.com/bundler/bundler/blob/master/lib/bundler/vendor/fileutils/lib/fileutils.rb</a></p>
<p>In the case of bundler, by separating the namespace as <code>Bundler::FileUtils</code>, even the version specified by the user is made available without conflict at the time of activate. However, this method can not be used with C extension library.</p>
<p>Since we want to use json/psych from the bundler team with rubygems/bundler to serialize data, we need about whether we can implement a way to avoid some kind of C extension on Ruby itself.</p>
<p>I discussed with <a class="user active user-mention" href="https://redmine.ruby-lang.org/users/7068">@indirect (André Arko)</a> who is maintainer of RubyGems/Bundler. We can resolve this problem like following feature of ruby.</p>
<pre><code>require_for_bundler 'json', '2.0.2'
</code></pre>
<p>When we declared above <code>require_for_bundler</code>, We put a json-2.0.2 to placed in a namespace like <code>Bundler::JSON</code>. There were similar issues in the past as well.</p>
<p><a href="https://bugs.ruby-lang.org/issues/10320" class="external">https://bugs.ruby-lang.org/issues/10320</a></p>
<p>I think that the way of writing <code>require 'json', version: '2.0.2', into: :Bundler</code> which extended the method like this issue seems like that. Also, in this use case, it seems to be enough to use <code>require 'json', version: :default, into: :Bundler</code> which forces the use of default gem.</p>
<p>Matz, How do you think about this feature?</p>