Ruby Issue Tracking System: Issueshttps://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112024-03-19T09:10:29ZRuby Issue Tracking System
Redmine Ruby master - Feature #20347 (Assigned): Separate docs task from allhttps://bugs.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 - Bug #20285 (Assigned): Stale inline method caches when refinement modules are reopenedhttps://bugs.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://bugs.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://bugs.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://bugs.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://bugs.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 #20112 (Assigned): Ractors not working properly in ruby 3.3.0https://bugs.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://bugs.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://bugs.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://bugs.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://bugs.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://bugs.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 #19908 (Assigned): Update to Unicode 15.1https://bugs.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://bugs.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> Test - Feature #19618 (Open): hash#dig testshttps://bugs.ruby-lang.org/issues/196182023-04-26T06:13:55Zhdiwan415 (Hasan Diwan)
<p>diff --git a/spec/ruby/core/hash/hash_spec.rb b/spec/ruby/core/hash/hash_spec.rb<br>
index 2ccb483120..3b583b338b 100644<br>
--- a/spec/ruby/core/hash/hash_spec.rb<br>
+++ b/spec/ruby/core/hash/hash_spec.rb<br>
@@ -1,4 +1,4 @@<br>
-require_relative '../../spec_helper'<br>
+require_relative "../../spec_helper"</p>
<p>describe "Hash" do<br>
it "includes Enumerable" do<br>
@@ -6,9 +6,18 @@<br>
end<br>
end</p>
<p>+describe "Hash#dig" do</p>
<ul>
<li>it "handles nested hash" do</li>
<li>{ foo: { bar: { baz: 2 } } }.dig(:foo).should == { :bar => { :baz => 2 } }</li>
<li>{ foo: { bar: { baz: 2 } } }.dig(:foo, :bar).should == { :baz => 2 }</li>
<li>{ foo: { bar: { baz: 2 } } }.dig(:foo, :bar, :baz).should == 2</li>
<li>{ foo: { bar: { baz: 2 } } }.dig(:BAZ).should.nil?</li>
<li>end<br>
+end</li>
<li>
</ul>
<p>describe "Hash#hash" do<br>
it "returns a value which doesn't depend on the hash order" do</p>
<ul>
<li>{ 0=>2, 11=>1 }.hash.should == { 11=>1, 0=>2 }.hash</li>
</ul>
<ul>
<li>{ 0 => 2, 11 => 1 }.hash.should == { 11 => 1, 0 => 2 }.hash<br>
end</li>
</ul>
<p>it "returns a value in which element values do not cancel each other out" do<br>
@@ -26,9 +35,9 @@<br>
end</p>
<p>it "returns the same hash for recursive hashes" do</p>
<ul>
<li>h = {} ; h[:x] = h</li>
<li>h.hash.should == {x: h}.hash</li>
<li>h.hash.should == {x: {x: h}}.hash</li>
</ul>
<ul>
<li>h = {}; h[:x] = h</li>
<li>h.hash.should == { x: h }.hash</li>
<li>h.hash.should == { x: { x: h } }.hash
<a name="This-is-because-heqlx-h"></a>
<h1 >This is because h.eql?(x: h)<a href="#This-is-because-heqlx-h" class="wiki-anchor">¶</a></h1>
<a name="Remember-that-if-two-objects-are-eql"></a>
<h1 >Remember that if two objects are eql?<a href="#Remember-that-if-two-objects-are-eql" class="wiki-anchor">¶</a></h1>
<a name="then-the-need-to-have-the-same-hash"></a>
<h1 >then the need to have the same hash.<a href="#then-the-need-to-have-the-same-hash" class="wiki-anchor">¶</a></h1>
</li>
</ul>
<p>@@ -36,9 +45,9 @@<br>
end</p>
<p>it "returns the same hash for recursive hashes through arrays" do</p>
<ul>
<li>h = {} ; rec = [h] ; h[:x] = rec</li>
<li>h.hash.should == {x: rec}.hash</li>
<li>h.hash.should == {x: [h]}.hash</li>
</ul>
<ul>
<li>h = {}; rec = [h]; h[:x] = rec</li>
<li>h.hash.should == { x: rec }.hash</li>
<li>h.hash.should == { x: [h] }.hash
<a name="Like-above-because-heqlx-h"></a>
<h1 >Like above, because h.eql?(x: [h])<a href="#Like-above-because-heqlx-h" class="wiki-anchor">¶</a></h1>
</li>
</ul>
<p>end</p>
<p>@@ -47,7 +56,7 @@<br>
a = 1<br>
b = 2</p>
<ul>
<li>
<pre><code>eval('{a:, b:}.should == { a: 1, b: 2 }')
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> eval("{a:, b:}.should == { a: 1, b: 2 }")
</code></pre>
end<br>
end<br>
end</li>
</ul>
<a name="adds-tests-forHashdig"></a>
<h1 >adds tests for.Hash#dig<a href="#adds-tests-forHashdig" class="wiki-anchor">¶</a></h1> Ruby master - Bug #19383 (Assigned): Time.now.zone encoding for German display language in Window...https://bugs.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://bugs.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 #19372 (Assigned): Proc objects are not traversed for shareable check during Ra...https://bugs.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://bugs.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://bugs.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 #19338 (Assigned): Ruby hangs when ouputting warnings inside ractor with VM loc...https://bugs.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://bugs.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://bugs.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://bugs.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> Test - Bug #19186 (Open): test2https://bugs.ruby-lang.org/issues/191862022-12-06T01:25:49Zshugo (Shugo Maeda)
<p>Hello, this is a test issue.<br>
This is a second line with umlaut: ü</p> Test - Bug #19185 (Open): testhttps://bugs.ruby-lang.org/issues/191852022-12-06T01:24:24Zshugo (Shugo Maeda)
<p>hello, this is a test issue.<br>
This is a second line.</p> Ruby master - Bug #18940 (Assigned): Ruby Ractor fails with IOError when handling higher concurrencyhttps://bugs.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://bugs.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 #18439 (Assigned): YJIT: Support Microsoft x86 calling conventionhttps://bugs.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://bugs.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://bugs.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://bugs.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://bugs.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 - Feature #17684 (Assigned): Remove `--disable-gems` from release version of Rubyhttps://bugs.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://bugs.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://bugs.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://bugs.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://bugs.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://bugs.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://bugs.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 - Misc #17376 (Assigned): Reduce number of GitHub Actionshttps://bugs.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://bugs.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://bugs.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://bugs.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 - Bug #16776 (Assigned): Regression in coverage libraryhttps://bugs.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://bugs.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 - Bug #16497 (Assigned): StringIO#internal_encoding is broken (more severely in 2.7)https://bugs.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://bugs.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 #16027 (Assigned): Update Ruby's dtrace / USDT API to match what is exposed...https://bugs.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://bugs.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://bugs.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://bugs.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://bugs.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 - Bug #15550 (Assigned): Windows - gem bin files - can't run from bash shellhttps://bugs.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 - Feature #15281 (Assigned): Speed up Set#intersect with size check.https://bugs.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 #14737 (Assigned): Split default gems into separate directory structurehttps://bugs.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://bugs.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 #14397 (Assigned): public, protected and private should return their argume...https://bugs.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://bugs.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 #13671 (Assigned): Regexp with lookbehind and case-insensitivity raises RegexpE...https://bugs.ruby-lang.org/issues/136712017-06-22T23:28:58Zdschweisguth (Dave Schweisguth)dave@schweisguth.org
<p>Here is a test program:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">test</span><span class="p">(</span><span class="n">description</span><span class="p">)</span>
<span class="k">begin</span>
<span class="k">yield</span>
<span class="nb">puts</span> <span class="s2">"</span><span class="si">#{</span><span class="n">description</span><span class="si">}</span><span class="s2"> is OK"</span>
<span class="k">rescue</span> <span class="no">RegexpError</span>
<span class="nb">puts</span> <span class="s2">"</span><span class="si">#{</span><span class="n">description</span><span class="si">}</span><span class="s2"> raises RegexpError"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="nb">test</span><span class="p">(</span><span class="s2">"ass, case-insensitive, special"</span><span class="p">)</span> <span class="p">{</span> <span class="sr">/(?<!ass)/i</span> <span class="o">=~</span> <span class="s1">'✨'</span> <span class="p">}</span>
<span class="nb">test</span><span class="p">(</span><span class="s2">"bss, case-insensitive, special"</span><span class="p">)</span> <span class="p">{</span> <span class="sr">/(?<!bss)/i</span> <span class="o">=~</span> <span class="s1">'✨'</span> <span class="p">}</span>
<span class="nb">test</span><span class="p">(</span><span class="s2">"as, case-insensitive, special"</span><span class="p">)</span> <span class="p">{</span> <span class="sr">/(?<!as)/i</span> <span class="o">=~</span> <span class="s1">'✨'</span> <span class="p">}</span>
<span class="nb">test</span><span class="p">(</span><span class="s2">"ss, case-insensitive, special"</span><span class="p">)</span> <span class="p">{</span> <span class="sr">/(?<!ss)/i</span> <span class="o">=~</span> <span class="s1">'✨'</span> <span class="p">}</span>
<span class="nb">test</span><span class="p">(</span><span class="s2">"ass, case-sensitive, special"</span><span class="p">)</span> <span class="p">{</span> <span class="sr">/(?<!ass)/</span> <span class="o">=~</span> <span class="s1">'✨'</span> <span class="p">}</span>
<span class="nb">test</span><span class="p">(</span><span class="s2">"ass, case-insensitive, regular"</span><span class="p">)</span> <span class="p">{</span> <span class="sr">/(?<!ass)/i</span> <span class="o">=~</span> <span class="s1">'x'</span> <span class="p">}</span>
</code></pre>
<p>Running the test program with Ruby 2.4.1 (macOS) gives</p>
<pre><code>ass, case-insensitive, special raises RegexpError
bss, case-insensitive, special raises RegexpError
as, case-insensitive, special is OK
ss, case-insensitive, special is OK
ass, case-sensitive, special is OK
ass, case-insensitive, regular is OK
</code></pre>
<p>The RegexpError is "invalid pattern in look-behind: /(?<!ass)/i (RegexpError)"</p>
<p>Side note: in the real code in which I found this error I was able to work around the error by using (?i) after the lookbehind instead of //i.</p>
<p>Running the test program with Ruby 2.3.4 does not report any RegexpErrors.</p>
<p>I think this is a regression, although I might be wrong and it might be saving me from an incorrect result with certain strings.</p> Ruby master - Feature #13129 (Assigned): Refinements cannot refine method_missing and respond_to_...https://bugs.ruby-lang.org/issues/131292017-01-14T17:21:59Zmatsuda (Akira Matsuda)ronnie@dio.jp
<p>Refinements with method_missing and respond_to_missing? behaves very strangely.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">C</span><span class="p">;</span> <span class="k">end</span>
<span class="n">using</span> <span class="no">Module</span><span class="p">.</span><span class="nf">new</span> <span class="p">{</span>
<span class="n">refine</span> <span class="no">C</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">x</span><span class="p">()</span> <span class="nb">p</span><span class="ss">:x</span><span class="p">;</span> <span class="k">end</span>
<span class="k">def</span> <span class="nf">method_missing</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="n">m</span> <span class="o">==</span> <span class="ss">:foo</span> <span class="p">?</span> <span class="nb">p</span><span class="p">(</span><span class="ss">:fooo!</span><span class="p">)</span> <span class="p">:</span> <span class="k">super</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">respond_to_missing?</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">include_private</span> <span class="o">=</span> <span class="kp">false</span><span class="p">)</span>
<span class="p">(</span><span class="n">m</span> <span class="o">==</span> <span class="ss">:foo</span><span class="p">)</span> <span class="o">||</span> <span class="k">super</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="p">}</span>
<span class="no">C</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">x</span>
<span class="nb">p</span> <span class="no">C</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">respond_to?</span> <span class="ss">:foo</span>
<span class="no">C</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">foo</span>
</code></pre>
<p>The script above doesn't respond_to :foo nor run :foo as expected.<br>
Actually, the result differs between ruby versions.</p>
<pre><code>% ruby -v t.rb
ruby 2.5.0dev (2017-01-14 trunk 57328) [x86_64-darwin15]
:x
false
t.rb:19:in `<main>': undefined method `foo' for #<C:0x007f90ca0fb240> (NoMethodError)
% ruby -v t.rb
ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-darwin15]
:x
false
t.rb:19:in `<main>': undefined method `foo' for #<C:0x007f80ae097780> (NoMethodError)
% ruby -v t.rb
ruby 2.3.3p222 (2016-11-21 revision 56859) [x86_64-darwin15]
:x
false
t.rb:19:in `<main>': undefined method `foo' for #<C:0x007fd89c83b518> (NoMethodError)
% ruby -v t.rb
ruby 2.2.6p396 (2016-11-15 revision 56800) [x86_64-darwin15]
:x
false
:fooo!
% ruby -v t.rb
ruby 2.1.10p492 (2016-04-01 revision 54464) [x86_64-darwin15.0]
:x
false
:fooo!
% ruby -v t.rb
ruby 2.0.0p648 (2015-12-16 revision 53162) [x86_64-darwin15.6.0]
t.rb:4: warning: Refinements are experimental, and the behavior may change in future versions of Ruby!
:x
false
:fooo!
</code></pre>
<p>What I can tell is that method_missing was broken at somewhere in between 2.2 and 2.3, and respond_to_missing? has never worked correctly.</p> Ruby master - Feature #13047 (Assigned): Use String literal instead of `String#+` for multiline p...https://bugs.ruby-lang.org/issues/130472016-12-17T14:21:49Zmtsmfm (Fumiaki Matsushima)mtsmfm@gmail.com
<p>Multiline pretty-printing of multiline strings is introduced. (<a href="https://bugs.ruby-lang.org/issues/12664" class="external">https://bugs.ruby-lang.org/issues/12664</a>)</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">></span> <span class="n">pp</span> <span class="s2">"bundler.rb"</span><span class="o">=></span> <span class="s2">"module Bundler</span><span class="se">\n</span><span class="s2"> BundlerError = Class.new(Exception)</span><span class="se">\n</span><span class="s2"> def self.setup</span><span class="se">\n</span><span class="s2"> end</span><span class="se">\n</span><span class="s2">end</span><span class="se">\n</span><span class="s2">"</span>
<span class="p">{</span><span class="s2">"bundler.rb"</span><span class="o">=></span>
<span class="s2">"module Bundler</span><span class="se">\n</span><span class="s2">"</span> <span class="o">+</span>
<span class="s2">" BundlerError = Class.new(Exception)</span><span class="se">\n</span><span class="s2">"</span> <span class="o">+</span>
<span class="s2">" def self.setup</span><span class="se">\n</span><span class="s2">"</span> <span class="o">+</span>
<span class="s2">" end</span><span class="se">\n</span><span class="s2">"</span> <span class="o">+</span>
<span class="s2">"end</span><span class="se">\n</span><span class="s2">"</span><span class="p">}</span>
</code></pre>
<p>It is awesome but we can use String literal instead of <code>String#+</code>:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">></span> <span class="n">pp</span> <span class="s2">"bundler.rb"</span><span class="o">=></span> <span class="s2">"module Bundler</span><span class="se">\n</span><span class="s2"> BundlerError = Class.new(Exception)</span><span class="se">\n</span><span class="s2"> def self.setup</span><span class="se">\n</span><span class="s2"> end</span><span class="se">\n</span><span class="s2">end</span><span class="se">\n</span><span class="s2">"</span>
<span class="p">{</span><span class="s2">"bundler.rb"</span><span class="o">=></span>
<span class="s2">"module Bundler</span><span class="se">\n</span><span class="s2">"</span> <span class="p">\</span>
<span class="s2">" BundlerError = Class.new(Exception)</span><span class="se">\n</span><span class="s2">"</span> <span class="p">\</span>
<span class="s2">" def self.setup</span><span class="se">\n</span><span class="s2">"</span> <span class="p">\</span>
<span class="s2">" end</span><span class="se">\n</span><span class="s2">"</span> <span class="p">\</span>
<span class="s2">"end</span><span class="se">\n</span><span class="s2">"</span><span class="p">}</span>
</code></pre>
<p>It seems that <code>pp</code> want to output evaluable snippet but we can override <code>String#+</code> so it may not work well.</p>
<p>Non-broken String will be:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">></span> <span class="n">pp</span> <span class="s2">"bundler.rb"</span><span class="o">=></span> <span class="s2">"module Bundler</span><span class="se">\n</span><span class="s2">end</span><span class="se">\n</span><span class="s2">"</span>
<span class="p">{</span><span class="s2">"bundler.rb"</span><span class="o">=></span> <span class="s2">"module Bundler</span><span class="se">\n</span><span class="s2">"</span> <span class="s2">"end</span><span class="se">\n</span><span class="s2">"</span><span class="p">}</span>
</code></pre>
<p>How do you think?</p>
<hr>
<p>I tried to write patch but I can't find a way to append "" to broken line only by current PP's API.</p> Ruby master - Bug #12725 (Assigned): Trying to use ./miniruby before it existshttps://bugs.ruby-lang.org/issues/127252016-09-05T05:04:23Zduerst (Martin Dürst)duerst@it.aoyama.ac.jpRuby master - Feature #12676 (Assigned): Significant performance increase, and code conciseness, ...https://bugs.ruby-lang.org/issues/126762016-08-15T01:48:12Zjzakiya (Jabari Zakiya)
<p>I earlier posted code to simplify the prime_division method in prime.rb.<br>
This made the code much more concise and readable/understandable, while<br>
also providing a small speed increase.</p>
<p>The code presented here for prime_division2 maintains the conciseness and<br>
readability, but uses a different/simpler algorithm to provide a significant<br>
speed increase over the current implementation of prime_division in prime.rb.</p>
<p>Timings for selected large primes are provided, run on CRuby 2.3.1.<br>
System: System76 3.5GHz I7 cpu laptop, Linux 64-bit OS in Virtual Box.</p>
<pre><code>n1 = 100_000_000_000_000_003
n2 = 200_000_000_000_000_003
n3 = 1_000_000_000_000_000_003
n1 n2 n3
prime_division 23.7 33.5 74.6
prime_division1 22.9 32.2 72.8
prime_division2 14.8 20.5 45.8
</code></pre>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">tm</span><span class="p">;</span> <span class="n">s</span> <span class="o">=</span> <span class="no">Time</span><span class="p">.</span><span class="nf">now</span><span class="p">;</span> <span class="k">yield</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="n">s</span> <span class="k">end</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">015</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="n">n</span> <span class="o">=</span> <span class="mi">100_000_000_000_000_003</span><span class="p">;</span> <span class="n">tm</span><span class="p">{</span> <span class="n">n</span><span class="p">.</span><span class="nf">prime_division</span> <span class="p">}</span>
<span class="o">=></span> <span class="mf">23.730239721</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">016</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="n">n</span> <span class="o">=</span> <span class="mi">100_000_000_000_000_003</span><span class="p">;</span> <span class="n">tm</span><span class="p">{</span> <span class="n">n</span><span class="p">.</span><span class="nf">prime_division1</span> <span class="p">}</span>
<span class="o">=></span> <span class="mf">22.877657172</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">017</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="n">n</span> <span class="o">=</span> <span class="mi">100_000_000_000_000_003</span><span class="p">;</span> <span class="n">tm</span><span class="p">{</span> <span class="n">n</span><span class="p">.</span><span class="nf">prime_division2</span> <span class="p">}</span>
<span class="o">=></span> <span class="mf">14.758561827</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">01</span><span class="mi">8</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="n">n</span> <span class="o">=</span> <span class="mi">200_000_000_000_000_003</span><span class="p">;</span> <span class="n">tm</span><span class="p">{</span> <span class="n">n</span><span class="p">.</span><span class="nf">prime_division</span> <span class="p">}</span>
<span class="o">=></span> <span class="mf">33.502851342</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">01</span><span class="mi">9</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="n">n</span> <span class="o">=</span> <span class="mi">200_000_000_000_000_003</span><span class="p">;</span> <span class="n">tm</span><span class="p">{</span> <span class="n">n</span><span class="p">.</span><span class="nf">prime_division1</span> <span class="p">}</span>
<span class="o">=></span> <span class="mf">32.23911595</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">020</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="n">n</span> <span class="o">=</span> <span class="mi">200_000_000_000_000_003</span><span class="p">;</span> <span class="n">tm</span><span class="p">{</span> <span class="n">n</span><span class="p">.</span><span class="nf">prime_division2</span> <span class="p">}</span>
<span class="o">=></span> <span class="mf">20.476660683</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">021</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1_000_000_000_000_000_003</span><span class="p">;</span> <span class="n">tm</span><span class="p">{</span> <span class="n">n</span><span class="p">.</span><span class="nf">prime_division</span> <span class="p">}</span>
<span class="o">=></span> <span class="mf">74.630244055</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">022</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1_000_000_000_000_000_003</span><span class="p">;</span> <span class="n">tm</span><span class="p">{</span> <span class="n">n</span><span class="p">.</span><span class="nf">prime_division1</span> <span class="p">}</span>
<span class="o">=></span> <span class="mf">72.778948947</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">023</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="n">n</span> <span class="o">=</span> <span class="mi">1_000_000_000_000_000_003</span><span class="p">;</span> <span class="n">tm</span><span class="p">{</span> <span class="n">n</span><span class="p">.</span><span class="nf">prime_division2</span> <span class="p">}</span>
<span class="o">=></span> <span class="mf">45.802756121</span>
</code></pre>
<ol>
<li>
<p>Current code for prime_division in prime.rb.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">prime_division</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">generator</span> <span class="o">=</span> <span class="no">Prime</span><span class="o">::</span><span class="no">Generator23</span><span class="p">.</span><span class="nf">new</span><span class="p">)</span>
<span class="k">raise</span> <span class="no">ZeroDivisionError</span> <span class="k">if</span> <span class="n">value</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">if</span> <span class="n">value</span> <span class="o"><</span> <span class="mi">0</span>
<span class="n">value</span> <span class="o">=</span> <span class="o">-</span><span class="n">value</span>
<span class="n">pv</span> <span class="o">=</span> <span class="p">[[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]]</span>
<span class="k">else</span>
<span class="n">pv</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">end</span>
<span class="n">generator</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">prime</span><span class="o">|</span>
<span class="n">count</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="p">(</span><span class="n">value1</span><span class="p">,</span> <span class="n">mod</span> <span class="o">=</span> <span class="n">value</span><span class="p">.</span><span class="nf">divmod</span><span class="p">(</span><span class="n">prime</span><span class="p">)</span>
<span class="n">mod</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">value1</span>
<span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">end</span>
<span class="k">if</span> <span class="n">count</span> <span class="o">!=</span> <span class="mi">0</span>
<span class="n">pv</span><span class="p">.</span><span class="nf">push</span> <span class="p">[</span><span class="n">prime</span><span class="p">,</span> <span class="n">count</span><span class="p">]</span>
<span class="k">end</span>
<span class="k">break</span> <span class="k">if</span> <span class="n">value1</span> <span class="o"><=</span> <span class="n">prime</span>
<span class="k">end</span>
<span class="k">if</span> <span class="n">value</span> <span class="o">></span> <span class="mi">1</span>
<span class="n">pv</span><span class="p">.</span><span class="nf">push</span> <span class="p">[</span><span class="n">value</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
<span class="k">end</span>
<span class="n">pv</span>
<span class="k">end</span>
</code></pre>
</li>
<li>
<p>Code simplification for current algorithm, increases conciseness/readability, with slight speedup.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">prime_division1</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">generator</span> <span class="o">=</span> <span class="no">Prime</span><span class="o">::</span><span class="no">Generator23</span><span class="p">.</span><span class="nf">new</span><span class="p">)</span>
<span class="k">raise</span> <span class="no">ZeroDivisionError</span> <span class="k">if</span> <span class="n">value</span> <span class="o">==</span> <span class="mi">0</span>
<span class="n">pv</span> <span class="o">=</span> <span class="n">value</span> <span class="o"><</span> <span class="mi">0</span> <span class="p">?</span> <span class="p">[[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]]</span> <span class="p">:</span> <span class="p">[]</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="p">.</span><span class="nf">abs</span>
<span class="n">generator</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">prime</span><span class="o">|</span>
<span class="n">count</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="p">(</span><span class="n">value1</span><span class="p">,</span> <span class="n">mod</span> <span class="o">=</span> <span class="n">value</span><span class="p">.</span><span class="nf">divmod</span><span class="p">(</span><span class="n">prime</span><span class="p">);</span> <span class="n">mod</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">value1</span>
<span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">end</span>
<span class="n">pv</span><span class="p">.</span><span class="nf">push</span> <span class="p">[</span><span class="n">prime</span><span class="p">,</span> <span class="n">count</span><span class="p">]</span> <span class="k">unless</span> <span class="n">count</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">break</span> <span class="k">if</span> <span class="n">prime</span> <span class="o">></span> <span class="n">value1</span>
<span class="k">end</span>
<span class="n">pv</span><span class="p">.</span><span class="nf">push</span> <span class="p">[</span><span class="n">value</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span> <span class="k">if</span> <span class="n">value</span> <span class="o">></span> <span class="mi">1</span>
<span class="n">pv</span>
<span class="k">end</span>
</code></pre>
</li>
<li>
<p>Change of algorithm, maintains conciseness/readability with significant speed increase.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">prime_division2</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">generator</span> <span class="o">=</span> <span class="no">Prime</span><span class="o">::</span><span class="no">Generator23</span><span class="p">.</span><span class="nf">new</span><span class="p">)</span>
<span class="k">raise</span> <span class="no">ZeroDivisionError</span> <span class="k">if</span> <span class="n">value</span> <span class="o">==</span> <span class="mi">0</span>
<span class="n">pv</span> <span class="o">=</span> <span class="n">value</span> <span class="o"><</span> <span class="mi">0</span> <span class="p">?</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="p">:</span> <span class="p">[]</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="p">.</span><span class="nf">abs</span>
<span class="n">sqrt_value</span> <span class="o">=</span> <span class="no">Math</span><span class="p">.</span><span class="nf">sqrt</span><span class="p">(</span><span class="n">value</span><span class="p">).</span><span class="nf">to_i</span>
<span class="n">generator</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">prime</span><span class="o">|</span>
<span class="k">break</span> <span class="k">if</span> <span class="n">prime</span> <span class="o">></span> <span class="n">sqrt_value</span>
<span class="k">while</span> <span class="n">value</span> <span class="o">%</span> <span class="n">prime</span> <span class="o">==</span> <span class="mi">0</span>
<span class="n">pv</span> <span class="o"><<</span> <span class="n">prime</span>
<span class="n">value</span> <span class="o">/=</span> <span class="n">prime</span>
<span class="n">sqrt_value</span> <span class="o">=</span> <span class="no">Math</span><span class="p">.</span><span class="nf">sqrt</span><span class="p">(</span><span class="n">value</span><span class="p">).</span><span class="nf">to_i</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">pv</span> <span class="o"><<</span> <span class="n">value</span> <span class="k">if</span> <span class="n">value</span> <span class="o">></span> <span class="mi">1</span>
<span class="n">pv</span><span class="p">.</span><span class="nf">group_by</span> <span class="p">{</span><span class="o">|</span><span class="n">prm</span><span class="o">|</span> <span class="n">prm</span> <span class="p">}.</span><span class="nf">map</span><span class="p">{</span><span class="o">|</span><span class="n">prm</span><span class="p">,</span> <span class="n">exp</span><span class="o">|</span> <span class="p">[</span><span class="n">prm</span><span class="p">,</span> <span class="n">exp</span><span class="p">.</span><span class="nf">size</span><span class="p">]</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
</li>
</ol> Ruby master - Feature #12653 (Assigned): Use wide WinAPI for rb_w32_getcwdhttps://bugs.ruby-lang.org/issues/126532016-08-03T18:33:23Zdavispuh (Dāvis Mosāns)
<p>Use wide WinAPI for rb_w32_getcwd.<br>
This will be needed so that Dir.pwd can support Unicode current directory on Windows.</p>
<p>I've attached a patch.</p> Ruby master - Feature #12639 (Assigned): Speed up require in RubyGems by 5xhttps://bugs.ruby-lang.org/issues/126392016-07-31T01:05:41Zsegiddins (Samuel Giddins)segiddins@segiddins.me
<p>This patch makes requiring an already-loaded file approximated 5x faster when the RubyGems mixin for require is present.<br>
Benchmarked via the following script:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s2">"rubygems"</span>
<span class="nb">require</span> <span class="s2">"benchmark/ips"</span>
<span class="no">Benchmark</span><span class="p">.</span><span class="nf">ips</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">"ruby"</span><span class="p">)</span> <span class="p">{</span> <span class="n">gem_original_require</span> <span class="s2">"rubygems"</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="s2">"rubygems"</span><span class="p">)</span> <span class="p">{</span> <span class="nb">require</span> <span class="s2">"rubygems"</span> <span class="p">}</span>
<span class="n">x</span><span class="p">.</span><span class="nf">compare!</span>
<span class="k">end</span>
</code></pre>
<p>I understand that it's not ideal to add new global functions, and I'd appreciate guidance on where else I could expose this functionality to ruby code.</p>
<p>Thanks :)</p> Ruby master - Bug #12445 (Assigned): Testing TestIO#test_open_fifo_does_not_block_other_threads r...https://bugs.ruby-lang.org/issues/124452016-05-31T10:15:12Zduerst (Martin Dürst)duerst@it.aoyama.ac.jp
<p>When I run <code>bin/ruby test/runner.rb test/ruby/test_*</code>, testing stops at <code>TestIO#test_open_fifo_does_not_block_other_threads</code>. Checking the task manager shows that this is a deadlock (there are two ruby interpreters running, but they don't use any CPU at all).</p>
<p>This is what I see for ages:</p>
<pre><code>[1589/4545] TestIO#test_open_fifo_does_not_block_other_threads
</code></pre> Ruby master - Bug #12444 (Assigned): Segmentation fault when running TestException#test_machine_s...https://bugs.ruby-lang.org/issues/124442016-05-31T10:10:48Zduerst (Martin Dürst)duerst@it.aoyama.ac.jp
<p>When I try to run <code>bin/ruby test/runner.rb test/ruby/test_*</code>, I get the error below. This is immediately followed by a very similar error for TestException#test_machine_stackoverflow_by_define_method.</p>
<pre><code>[ 942/4545] TestException#test_machine_stackoverflow = 1.27 s
19) Failure:
TestException#test_machine_stackoverflow [/cygdrive/c/Data/ruby/test/ruby/test_exception.rb:577]:
pid 16416 killed by SIGABRT (signal 6) (core dumped)
| -:7: [BUG] Segmentation fault at 0x000000ffe03fc0
| ruby 2.4.0dev (2016-05-31 trunk 55228) [x86_64-cygwin]
|
| -- Control frame information -----------------------------------------------
| c:0690 p:0014 s:1387 e:001386 LAMBDA -:7 [FINISH]
| c:0689 p:0014 s:1385 e:001384 LAMBDA -:7 [FINISH]
| c:0688 p:0014 s:1383 e:001382 LAMBDA -:7 [FINISH]
| c:0687 p:0014 s:1381 e:001380 LAMBDA -:7 [FINISH]
| c:0686 p:0014 s:1379 e:001378 LAMBDA -:7 [FINISH]
| c:0685 p:0014 s:1377 e:001376 LAMBDA -:7 [FINISH]
| c:0684 p:0014 s:1375 e:001374 LAMBDA -:7 [FINISH]
| c:0683 p:0014 s:1373 e:001372 LAMBDA -:7 [FINISH]
| c:0682 p:0014 s:1371 e:001370 LAMBDA -:7 [FINISH]
| c:0681 p:0014 s:1369 e:001368 LAMBDA -:7 [FINISH]
</code></pre>
<p>[very long list, ending in]</p>
<pre><code>| c:0009 p:0014 s:0025 e:000024 LAMBDA -:7 [FINISH]
| c:0008 p:0014 s:0023 e:000022 LAMBDA -:7 [FINISH]
| c:0007 p:0014 s:0021 e:000020 LAMBDA -:7 [FINISH]
| c:0006 p:0014 s:0019 e:000018 LAMBDA -:7 [FINISH]
| c:0005 p:0014 s:0017 e:000016 LAMBDA -:7 [FINISH]
| c:0004 p:0028 s:0015 E:001588 BLOCK -:8
| c:0003 p:0052 s:0012 e:000011 METHOD /cygdrive/c/Data/ruby/test/lib/test/unit/assertions.rb:74
| c:0002 p:0047 s:0004 E:000610 EVAL -:6 [FINISH]
| c:0001 p:0000 s:0002 E:001930 (none) [FINISH]
|
| -- Ruby level backtrace information ----------------------------------------
| -:6:in `<main>'
| /cygdrive/c/Data/ruby/test/lib/test/unit/assertions.rb:74:in `assert_raise'
| -:8:in `block in <main>'
| -:7:in `block (2 levels) in <main>'
| -:7:in `block (2 levels) in <main>'
| -:7:in `block (2 levels) in <main>'
| -:7:in `block (2 levels) in <main>'
| -:7:in `block (2 levels) in <main>'
| -:7:in `block (2 levels) in <main>'
| -:7:in `block (2 levels) in <main>'
</code></pre>
<p>[again very long list, probably about same length, ending with]</p>
<pre><code>| -:7:in `block (2 levels) in <main>'
| -:7:in `block (2 levels) in <main>'
| -:7:in `block (2 levels) in <main>'
| -:7:in `block (2 levels) in <main>'
| -:7:in `block (2 levels) in <main>'
| -:7:in `block (2 levels) in <main>'
| -:7:in `block (2 levels) in <main>'
| -:7:in `block (2 levels) in <main>'
| -:7:in `block (2 levels) in <main>'
|
| -- Other runtime information -----------------------------------------------
|
| * Loaded script: -
|
| * Loaded features:
|
| 0 enumerator.so
| 1 thread.rb
| 2 rational.so
| 3 complex.so
| 4 /cygdrive/c/Data/ruby/lib/ruby/2.4.0/x86_64-cygwin/enc/encdb.so
| 5 /cygdrive/c/Data/ruby/lib/ruby/2.4.0/x86_64-cygwin/enc/trans/transdb.so
| 6 /cygdrive/c/Data/ruby/lib/ruby/2.4.0/x86_64-cygwin/enc/windows_31j.so
| 7 /cygdrive/c/Data/ruby/lib/ruby/vendor_ruby/unicode_normalize.rb
| 8 /cygdrive/c/Data/ruby/lib/ruby/vendor_ruby/optparse.rb
| 9 /cygdrive/c/Data/ruby/lib/ruby/2.4.0/x86_64-cygwin/rbconfig.rb
| 10 /cygdrive/c/Data/ruby/test/lib/leakchecker.rb
| 11 /cygdrive/c/Data/ruby/test/lib/minitest/unit.rb
| 12 /cygdrive/c/Data/ruby/lib/ruby/vendor_ruby/prettyprint.rb
| 13 /cygdrive/c/Data/ruby/lib/ruby/vendor_ruby/pp.rb
| 14 /cygdrive/c/Data/ruby/test/lib/test/unit/assertions.rb
| 15 /cygdrive/c/Data/ruby/lib/ruby/vendor_ruby/open3.rb
| 16 /cygdrive/c/Data/ruby/lib/ruby/vendor_ruby/timeout.rb
| 17 /cygdrive/c/Data/ruby/test/lib/find_executable.rb
| 18 /cygdrive/c/Data/ruby/lib/ruby/2.4.0/x86_64-cygwin/rbconfig/sizeof.so
| 19 /cygdrive/c/Data/ruby/test/lib/envutil.rb
| 20 /cygdrive/c/Data/ruby/test/lib/test/unit/testcase.rb
| 21 /cygdrive/c/Data/ruby/test/lib/test/unit.rb
|
| [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
|
</code></pre> Ruby master - Bug #12442 (Assigned): TestArgf#test_textmode fails on cygwinhttps://bugs.ruby-lang.org/issues/124422016-05-31T10:01:19Zduerst (Martin Dürst)duerst@it.aoyama.ac.jp
<p>When I try to run <code>bin/ruby test/runner.rb test/ruby/test_*</code> (because <code>make test-all</code> doesn't work), the first failure that I get is as below.</p>
<pre><code>$ bin/ruby test/runner.rb test/ruby/test_*
Run options:
# Running tests:
[ 156/4545] TestArgf#test_textmode = 1.60 s
1) Failure:
TestArgf#test_textmode [/cygdrive/c/Data/ruby/test/ruby/test_argf.rb:685]:
<a href="/issues/5268">[ruby-core:39234]</a>.
<"1\n2\n3\n4\n5\n6\n"> expected but was
<"1\n2\n3\n4\n5\r\n6\r\n">.
</code></pre> Ruby master - Bug #12040 (Assigned): [Win32] File.stat fails on a mounted volumehttps://bugs.ruby-lang.org/issues/120402016-02-01T08:13:24Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<p>On Windows, <code>File.stat</code> fails on the volume mount point directory whose name contains <code>"..."</code>.</p>
<p>Where <code>%vol%</code> is the volume ID of a new VHD volume,</p>
<pre><code>C:> set vol
\\?\Volume{3C458AE9-C8B1-11E5-A233-0800271D089F}\
C:> mkdir x...y
C:> mountvol x...y %vol%
C:> .\miniruby -e "p Dir.chdir('x...y'){File.stat('.')}" -e "p File.stat('x...y')"
#<File::Stat dev=0x2, ino=1407374883553285, mode=040755, nlink=1, uid=0, gid=0, rdev=0x2, size=4096, blksize=nil, blocks=nil, atime=2016-02-01 16:35:45 +0900, mtime=2016-02-01 16:35:45 +0900, ctime=2016-02-01 16:35:45 +0900>
-e:2:in `stat': No such file or directory @ rb_file_s_stat - x...y (Errno::ENOENT)
from -e:2:in `<main>'
</code></pre>
<p>Note that <code>Dir.chdir</code> and <code>File.stat</code> there succeed.<br>
This failures depends on the mount point name, because of <code>check_valid_dir()</code>.</p> Ruby master - Feature #11625 (Assigned): Unlock GVL for SHA1 calculationshttps://bugs.ruby-lang.org/issues/116252015-10-27T19:34:06Ztenderlovemaking (Aaron Patterson)tenderlove@ruby-lang.org
<p>I'm trying to calculate many sha1 checksums, but the current sha1 implementation doesn't unlock the GVL, so I can't do it in parallel. I've attached a patch that unlocks the GVL when calculating sha1sums so that I can do them in parallel.</p>
<p>The good point about this patch is that I can calculate sha1's in parallel. Here is the test code I'm using:</p>
<pre><code>require 'digest/sha1'
require 'thread'
Thread.abort_on_exception = true
THREADS = (ENV['THREADS'] || 1).to_i
store = 'x' * (ENV['SIZE'] || 1024).to_i
queue = Queue.new
600000.times do
queue << store
end
THREADS.times { queue << nil }
ts = THREADS.times.map {
Thread.new {
while work = queue.pop
Digest::SHA1.hexdigest(work)
end
}
}
ts.each(&:join)
</code></pre>
<p>Here is what the output looks like after I've applied the patch:</p>
<pre><code>[aaron@TC ruby (trunk)]$ THREADS=1 SIZE=4096 time ./ruby test.rb
22.62 real 21.78 user 0.66 sys
[aaron@TC ruby (trunk)]$ THREADS=4 SIZE=4096 time ./ruby test.rb
15.87 real 34.53 user 8.27 sys
[aaron@TC ruby (trunk)]$
</code></pre>
<p>The digests that I'm calculating are for fairly large strings, so this patch works well for me. The downsides are that it seems slightly slower (though I'm not sure that it's significant) with a single thread:</p>
<p>Test code:</p>
<pre><code>require 'benchmark/ips'
require 'digest/sha1'
Benchmark.ips do |x|
x.report('sha1') { Digest::SHA1.hexdigest('x' * 4096) }
end
</code></pre>
<p>Before my patch (higher numbers are better):</p>
<pre><code>[aaron@TC ruby (trunk)]$ ./ruby shaips.rb
Calculating -------------------------------------
sha1 2.604k i/100ms
-------------------------------------------------
sha1 27.441k (± 3.9%) i/s - 138.012k
</code></pre>
<p>After my patch:</p>
<pre><code>[aaron@TC ruby (trunk)]$ ./ruby shaips.rb
Calculating -------------------------------------
sha1 2.419k i/100ms
-------------------------------------------------
sha1 25.848k (± 2.8%) i/s - 130.626k
</code></pre>
<p>Other downside is that I changed the <code>update</code> method to dup strings so that the GVL can be safely released.</p>
<p>This patch pays off for me because of the size of the strings I'm working with, but I'm not sure if it's fine for the general case.</p> Ruby master - Feature #11028 (Assigned): standalone running single file ( zipped archives of ruby...https://bugs.ruby-lang.org/issues/110282015-04-03T03:44:09Zzaxebo1 (zaxebo zaxebo)zaxebo1@gmail.com
<p>standalone running single file ( zipped archives of ruby code) running <strong>without installation</strong> using "gem install ..."<br>
prior examples in other languages:</p>
<pre><code>python myprg.pyz
java -jar myprg.jar
</code></pre>
<a name="Detailed-Description"></a>
<h2 >Detailed Description:<a href="#Detailed-Description" class="wiki-anchor">¶</a></h2>
<p>In python, if i have multiple program files: "<code>a1.py</code>, <code>a2.py</code>, <code>__main__.py</code>,<br>
<code>dir1/b1.py</code>, <code>dir1/b2.py</code>" and then i zip it as myprogram1.pyz<br>
then i can run it as "python myprogram.pyz" (<code>__main__.py</code> inside the zip<br>
file will be executed first). It is easy to distribute a single file<br>
myprogram1.pyz</p>
<p>see: <a href="http://blogs.gnome.org/jamesh/2012/05/21/python-zip-files/" class="external">http://blogs.gnome.org/jamesh/2012/05/21/python-zip-files/</a></p>
<hr>
<p>in java also we can bundle all the .class files into a single .jar file<br>
and run it</p>
<pre><code>java -jar myprogram1.jar
</code></pre>
<hr>
<p>Currently in ruby the ".gem" file requires installation using "gem install ...". Then it gives some program file for running.<br>
What i am asking is that some gem file should have manifest with which they can run directly without installing</p>
<p>That is, i request you to kind provide a feature in ruby that if i have lots of files like: <code>a1.rb</code>, <code>a2.rb</code>, <code>__main__.rb</code>, <code>dir1/a4.rb</code> etc.<br>
(say, which uses Ruby-GTK for a Desktop application). Then i should be able to bundle them as zip file, say myprog1.zip or myprog1.pz ( rbz=ruby's zipped executable archive).<br>
And then i can distribute this "single file" and execute it as:</p>
<pre><code>ruby myprog1.rbz
</code></pre>
<p>This will execute the <code>__main__.rb</code> file among all the other .rb files,<br>
inside this .zip archive myprog1.rbz .<br>
Note: this .rbz file extension can be .gemz or whatever, but this functionality of "standalone running zipped archives of ruby code running without installation" is essential</p> Ruby master - Feature #10637 (Assigned): Puppet orchestration on vagrant fails with Error: Non-HT...https://bugs.ruby-lang.org/issues/106372014-12-23T18:59:56Zeshenayo (Eshe Pickett)eshe.pickett@gmail.com
<p>I encountered this issue while bringing up a VM using vagrant with virtualbox. I am using puppet to do some provisioning</p>
<p>==> default: Notice: Downloading from <a href="https://forge.puppetlabs.com" class="external">https://forge.puppetlabs.com</a> ...<br>
==> default: Error: Non-HTTP proxy URI: https://[proxy]:[port]/ class is: URI::HTTPS<br>
==> default: Error: Try 'puppet help module install' for usage<br>
==> default: Notice: Preparing to install into /etc/puppet/modules ...<br>
==> default: Notice: Downloading from <a href="https://forge.puppetlabs.com" class="external">https://forge.puppetlabs.com</a> ...<br>
==> default: Error: Non-HTTP proxy URI: https://[proxy]:[port]/ class is: URI::HTTPS<br>
==> default: Error: Try 'puppet help module install' for usage</p>
<p>I put in the print out to see what class in the above output</p>
<p>Puppet is using https to download modules, and it hits the open_http function</p>
<p>def OpenURI.open_http(buf, target, proxy, options) # :nodoc:<br>
if proxy<br>
proxy_uri, proxy_user, proxy_pass = proxy<br>
raise "Non-HTTP proxy URI: #{proxy_uri} class is: #{proxy_uri.class}" if proxy_uri.class != URI::HTTP<br>
end</p>
<p>I am new to ruby, so am unsure if this is the expected behavior. I have a work around, I set https_proxy to use the http_proxy, however, this is not by any means a permanent solution. Alternatively, I could change the ruby code to allow both HTTP and HTTPS URIs, please advise.</p> Ruby master - Feature #9830 (Assigned): Support for GOST private/public keyshttps://bugs.ruby-lang.org/issues/98302014-05-11T20:34:05ZEnvek (Andrey Novikov)envek@envek.name
<p>Hello everyone.</p>
<p>We're required to use GOST encryption algorithms for signing requests, interacting with HTTPS services with client certificate authentication and so on.</p>
<p>OpenSSL 1.0.0 is bundled with GOST engine, and, if correctly configured, can handle all of these tasks from command line. Also see <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Ruby doesn't respect system OpenSSL configuration (Closed)" href="https://bugs.ruby-lang.org/issues/9822">#9822</a>.</p>
<p><strong>Issue</strong></p>
<p>Ruby can't read GOST private and public keys:</p>
<pre><code>ruby> privkey = OpenSSL::PKey.read(File.read('gost_r_34_10_2001_private_key.pem'))
OpenSSL::PKey::PKeyError: unsupported key type
ruby> # Same for public keys
ruby> crt = OpenSSL::X509::Certificate.new(File.read('gost_r_34_10_2001_certificate.pem'))
ruby> crt.public_key
OpenSSL::PKey::PKeyError: unsupported key type
</code></pre>
<p>The problem is there is no "Generic PKey" class in Ruby's OpenSSL.</p>
<p>In source in <code>ext/openssl/openssl_pkey.c</code> at line 76 in method <code>ossl_pkey_new</code> there is examination of key type and creating appropriate Ruby classes. But GOST R 34.10-2001 key type have type <code>NID_id_GostR3410_2001</code> (811), and Ruby fails.</p>
<p><strong>Possible solution</strong></p>
<p>GOST keys are EC keys in fact (at least for GOST R 34.10-2001). And, if I add <code>case NID_id_GostR3410_2001:</code> right before <code>case EVP_PKEY_EC:</code> and remove checks about key type in <code>ext/openssl/openssl_pkey_ec.c</code> – everything will work.</p>
<p>To illustrate this, I've attached required patches (one from issue <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Ruby doesn't respect system OpenSSL configuration (Closed)" href="https://bugs.ruby-lang.org/issues/9822">#9822</a>), self-signed GOST R 34.10-2001 certificate with private key and two test scripts.</p>
<p><strong>NOTE</strong>: You will need OpenSSL version 1.0.0 or newer with correct configuration, see links below!</p>
<p><strong>Question</strong></p>
<p>How should GOST keys support implemented in Ruby? Should it even use <code>OpenSSL::PKey::EC</code>, or, may be, subclass from it?</p>
<p>I'm not experienced neither in C programming nor in cryptography, but I would be glad to help with the implementation of this.</p>
<p><strong>Further information</strong></p>
<ul>
<li>
<strong>README.gost</strong>: Instructions for setting up OpenSSL and usage: <a href="https://github.com/openssl/openssl/blob/master/engines/ccgost/README.gost" class="external">https://github.com/openssl/openssl/blob/master/engines/ccgost/README.gost</a>
</li>
<li>
<strong>OpenSSL GOST engine source</strong>: <a href="https://github.com/openssl/openssl/tree/master/engines/ccgost" class="external">https://github.com/openssl/openssl/tree/master/engines/ccgost</a>
</li>
<li>
<strong>RFC 5830</strong>: GOST 28147-89: Encryption, Decryption, and Message Authentication Code (MAC) Algorithms:<br>
<a href="http://tools.ietf.org/html/rfc5830" class="external">http://tools.ietf.org/html/rfc5830</a>
</li>
<li>
<strong>RFC 5831</strong>: GOST R 34.11-94: Hash Function Algorithm:<br>
<a href="http://tools.ietf.org/html/rfc5831" class="external">http://tools.ietf.org/html/rfc5831</a>
</li>
<li>
<strong>RFC 5832</strong>: GOST R 34.10-2001: Digital Signature Algorithm:<br>
<a href="http://tools.ietf.org/html/rfc5832" class="external">http://tools.ietf.org/html/rfc5832</a>
</li>
<li>
<strong>RFC 4491</strong>: Using the GOST Algorithms with the Internet X.509 Public Key Infrastructure:<br>
<a href="http://tools.ietf.org/html/rfc4491" class="external">http://tools.ietf.org/html/rfc4491</a>
</li>
<li>
<strong>RFC 4490</strong>: Using the GOST Algorithms with Cryptographic Message Syntax (CMS):<br>
<a href="http://tools.ietf.org/html/rfc4490" class="external">http://tools.ietf.org/html/rfc4490</a>
</li>
<li>
<strong>RFC 4357</strong>: Additional Cryptographic Algorithms for Use with GOST Algorithms</li>
<li>Some stackoverflow.com related questions: <a href="http://stackoverflow.com/questions/12868384/openssl-gost-parameter-set" class="external">http://stackoverflow.com/questions/12868384/openssl-gost-parameter-set</a> and <a href="http://stackoverflow.com/questions/14580340/generate-gost-34-10-2001-keypair-and-save-it-to-some-keystore" class="external">http://stackoverflow.com/questions/14580340/generate-gost-34-10-2001-keypair-and-save-it-to-some-keystore</a>
</li>
</ul> Ruby master - Feature #9816 (Assigned): 文字列内の数字を数値として比較するメソッドhttps://bugs.ruby-lang.org/issues/98162014-05-08T09:37:26Znaruse (Yui NARUSE)naruse@airemix.jp
<p>文字列内の数字を数値として比較するメソッドを追加しませんか</p>
<p>そのような比較は一般的な用途としてはGUIシェルのファイラーが比較に用いており、<br>
Windows では StrCmpLogicalW が、OS X では NSString:compare:options:へのNSNumericSearch定数が提供されています。<br>
<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb759947(v=vs.85).aspx" class="external">http://msdn.microsoft.com/en-us/library/windows/desktop/bb759947(v=vs.85).aspx</a><br>
<a href="https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/c/econst/NSNumericSearch" class="external">https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/c/econst/NSNumericSearch</a></p>
<p>上記のような処理自体はさほど難しいものではありませんが、Rubyレベルで実装すると大量のオブジェクトを作ってしまいます。<br>
例えば <code>Gem::Version.new("2.1.10".freeze)<=>Gem::Version.new("2.1.9".freeze)</code> は47個、<br>
<code>"2.1.10".freeze.split('.').map(&:to_i)<=>"2.1.9".freeze.split('.').map(&:to_i)</code> だと16個のオブジェクトを作ります。<br>
<code>"2.1.10".freeze.numericcmp"2.1.9".freeze</code> ならば、もちろんオブジェクトは一つも作りません。</p>
<p>なお、上記の例でも示唆していますが、本メソッドは Ruby のバージョン表記の TEENY が2桁になった場合の比較に用いることができます。</p>
<p>パッチは以下の通りです。<br>
なお、メソッド名は String#numericcmp としています。<br>
(String#casecmpを念頭に置いた)</p>
<pre><code>diff --git a/string.c b/string.c
index c589c80..66f667f 100644
--- a/string.c
+++ b/string.c
@@ -2569,6 +2569,131 @@ rb_str_casecmp(VALUE str1, VALUE str2)
return INT2FIX(-1);
}
+VALUE
+numerical_compare(const char **pp1, const char *p1end, const char **pp2, const char *p2end)
+{
+ const char *s1 = *pp1, *p1, *s2 = *pp2, *p2;
+ ptrdiff_t len1, len2;
+ int r;
+
+ while (s1 < p1end && *s1 == '0') s1++;
+ p1 = s1;
+ while (p1 < p1end && ISDIGIT(*p1)) p1++;
+ len1 = p1 - s1;
+
+ while (s2 < p2end && *s2 == '0') s2++;
+ p2 = s2;
+ while (p2 < p2end && ISDIGIT(*p2)) p2++;
+ len2 = p2 - s2;
+
+ if (len1 != len2) {
+ return INT2FIX(len1 < len2 ? -1 : 1);
+ }
+
+ r = memcmp(s1, s2, len1);
+ if (r) return r < 0 ? INT2FIX(-1) : INT2FIX(1);
+
+ len1 = s1 - *pp1;
+ len2 = s2 - *pp2;
+ if (len1 != len2) {
+ return INT2FIX(len1 < len2 ? -1 : 1);
+ }
+
+ *pp1 = p1;
+ *pp2 = p2;
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * str.numericcmp(other_str) -> -1, 0, +1 or nil
+ *
+ * Variant of <code>String#<=></code>, which considers digits in strings
+ * are numeric value..
+ *
+ * "a1".numericcmp("a1") #=> 0
+ * "aa".numericcmp("a1") #=> 1
+ * "a1".numericcmp("aa") #=> -1
+ * "a1".numericcmp("a01") #=> -1
+ * "2.1.2".numericcmp("2.1.10") #=> 1
+ */
+
+static VALUE
+rb_str_numericcmp(VALUE str1, VALUE str2)
+{
+ long len;
+ rb_encoding *enc;
+ const char *p1, *p1end, *p2, *p2end;
+
+ StringValue(str2);
+ enc = rb_enc_compatible(str1, str2);
+ if (!enc) {
+ return Qnil;
+ }
+
+ p1 = RSTRING_PTR(str1); p1end = RSTRING_END(str1);
+ p2 = RSTRING_PTR(str2); p2end = RSTRING_END(str2);
+ if (single_byte_optimizable(str1) && single_byte_optimizable(str2)) {
+ while (p1 < p1end && p2 < p2end) {
+ if (ISDIGIT(*p1)) {
+ if (ISDIGIT(*p2)) {
+ VALUE r = numerical_compare(&p1, p1end, &p2, p2end);
+ if (!NIL_P(r)) return r;
+ }
+ else {
+ return INT2FIX(-1);
+ }
+ }
+ else if (ISDIGIT(*p2)) {
+ return INT2FIX(1);
+ }
+ if (*p1 != *p2) return INT2FIX(*p1 < *p2 ? -1 : 1);
+ p1++;
+ p2++;
+ }
+ }
+ else {
+ while (p1 < p1end && p2 < p2end) {
+ int l1, c1 = rb_enc_ascget(p1, p1end, &l1, enc);
+ int l2, c2 = rb_enc_ascget(p2, p2end, &l2, enc);
+
+ if (0 <= c1 && 0 <= c2) {
+ if (ISDIGIT(*p1)) {
+ if (ISDIGIT(*p2)) {
+ VALUE r = numerical_compare(&p1, p1end, &p2, p2end);
+ if (!NIL_P(r)) return r;
+ }
+ else {
+ return INT2FIX(-1);
+ }
+ }
+ else if (ISDIGIT(*p2)) {
+ return INT2FIX(1);
+ }
+ if (*p1 != *p2) return INT2FIX(*p1 < *p2 ? -1 : 1);
+ p1++;
+ p2++;
+ }
+ else {
+ int r;
+ l1 = rb_enc_mbclen(p1, p1end, enc);
+ l2 = rb_enc_mbclen(p2, p2end, enc);
+ len = l1 < l2 ? l1 : l2;
+ r = memcmp(p1, p2, len);
+ if (r != 0)
+ return INT2FIX(r < 0 ? -1 : 1);
+ if (l1 != l2)
+ return INT2FIX(l1 < l2 ? -1 : 1);
+ }
+ p1 += l1;
+ p2 += l2;
+ }
+ }
+ if (RSTRING_LEN(str1) == RSTRING_LEN(str2)) return INT2FIX(0);
+ if (RSTRING_LEN(str1) > RSTRING_LEN(str2)) return INT2FIX(1);
+ return INT2FIX(-1);
+}
+
static long
rb_str_index(VALUE str, VALUE sub, long offset)
{
@@ -8721,6 +8846,7 @@ Init_String(void)
rb_define_method(rb_cString, "eql?", rb_str_eql, 1);
rb_define_method(rb_cString, "hash", rb_str_hash_m, 0);
rb_define_method(rb_cString, "casecmp", rb_str_casecmp, 1);
+ rb_define_method(rb_cString, "numericcmp", rb_str_numericcmp, 1);
rb_define_method(rb_cString, "+", rb_str_plus, 1);
rb_define_method(rb_cString, "*", rb_str_times, 1);
rb_define_method(rb_cString, "%", rb_str_format_m, 1);
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index 8366424..f9c788b 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -2104,6 +2104,29 @@ class TestString < Test::Unit::TestCase
assert_equal(1, "\u3042B".casecmp("\u3042a"))
end
+ def test_numericcmp
+ assert_equal(-1, "2.1.0".numericcmp("2.1.1"))
+ assert_equal(-1, "2.1.9".numericcmp("2.1.10"))
+ assert_equal( 0, "a1".numericcmp("a1"))
+ assert_equal( 1, "aa".numericcmp("a1"))
+ assert_equal(-1, "a1".numericcmp("aa"))
+ assert_equal(-1, "a1".numericcmp("a01"))
+ assert_equal(-1, "a0001".numericcmp("a00001"))
+ assert_equal( 0, "a1a".numericcmp("a1a"))
+ assert_equal( 1, "a1b".numericcmp("a1a"))
+ assert_equal(-1, "a9a".numericcmp("a10a"))
+ assert_equal( 1, "b".numericcmp("a"))
+ assert_equal( 0, "\u30421".numericcmp("\u30421"))
+ assert_equal( 1, "\u3042\u3042".numericcmp("\u30421"))
+ assert_equal(-1, "\u30421".numericcmp("\u3042\u3042"))
+ assert_equal(-1, "\u30421".numericcmp("\u304201"))
+ assert_equal(-1, "\u30420001".numericcmp("\u304200001"))
+ assert_equal( 0, "\u30421\u3042".numericcmp("\u30421\u3042"))
+ assert_equal( 1, "\u30421\u3044".numericcmp("\u30421\u3042"))
+ assert_equal(-1, "\u30429\u3042".numericcmp("\u304210\u3042"))
+ assert_equal( 1, "\u3044".numericcmp("\u3042"))
+ end
+
def test_upcase2
assert_equal("\u3042AB", "\u3042aB".upcase)
end
</code></pre> Ruby master - Feature #9755 (Assigned): Thread::Backtrace::Location#defined_classhttps://bugs.ruby-lang.org/issues/97552014-04-18T09:22:23Zshugo (Shugo Maeda)
<p>I'd like Thread::Backtrace::Location#defined_class.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">X</span>
<span class="k">def</span> <span class="nf">foo</span>
<span class="nb">p</span> <span class="n">caller_locations</span><span class="p">.</span><span class="nf">first</span><span class="p">.</span><span class="nf">defined_class</span> <span class="c1">#=> Y</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">Y</span>
<span class="k">def</span> <span class="nf">bar</span>
<span class="no">X</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">foo</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="no">Y</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">bar</span>
</code></pre>
<p>nobu created a patch:</p>
<p><a href="https://github.com/nobu/ruby/compare/backtrace-self%2Bclass" class="external">https://github.com/nobu/ruby/compare/backtrace-self%2Bclass</a></p>
<p>But this patch has two problems:</p>
<ol>
<li>The patch adds Thread::Backtrace::Location#self, but it's weird that a location has self.</li>
<li>Thread::Backtrace::Location#class conflicts with Kernel#class.<br>
So I proposed defined_class as the method name.</li>
</ol> Ruby master - Feature #8271 (Assigned): Proposal for moving to a more visible, formal process for...https://bugs.ruby-lang.org/issues/82712013-04-16T05:35:58Zheadius (Charles Nutter)headius@headius.com
<p>Proposal for moving to a more visible, formal process for feature requests.</p>
<ol>
<li>Introduction</li>
</ol>
<p>In order to make it clear that an issue or change to MRI is a visible feature change all implementations will need to consider implementing, I propose that we move all feature requests into a separate Redmine project. I see the following benefits to this arrangement:</p>
<ul>
<li>Features are always in one place. One-stop-shopping for implementers to track changes to "Ruby" that are not specific to MRI.</li>
<li>No confusion about where feature requests should be filed. Currently, people usually file feature requests against "trunk", but sometimes against version-specific projects. It's also valid to say that a feature improvement or clarification is not specific to trunk. Tracking features separate from "trunk" and version-specific Redmine projects keeps the process localized to one Redmine project.</li>
<li>Ability to add fields to "feature" issues that do not have relevance for "bugs". For example, bugs do not usually need approval from matz, but features could have an "approved by matz" field. We could also have other metadata tracking other implementations, such as "approved by implementations" or "affects implementations" with drop-downs for known impls. One-stop-shopping to know whether a given impl is affected and/or has agreed to add the feature.</li>
<li>More visible process for folks in the community that can't follow the current process or don't believe there's a process in place.</li>
</ul>
<p>I propose that the project be called CommonRuby (already created and under some use) and be a top-level entry on bugs.ruby-lang.org.</p>
<ol start="2">
<li>Processes</li>
</ol>
<p>For issues that are obviously new features (i.e. user knows to select "feature" in the current tracker), issues would be filed directly in CommonRuby. Discussion proceeds exactly as the current process, perhaps with additional issue fields added that allow tracking matz approval, etc, as stated in §1.</p>
<p>Issues that are approved for a Ruby version will have fields/metadata to indicate at which version the feature is available. This may mean specifying multiple releases if, for example, 2.0.1 and 1.9.3p400 would both see a feature added (just saying 1.9.3p400 is insufficient since the feature does not exist in 2.0.0. This avoids having to track features through the backport process to know if there are multiple releases that contain the feature.</p>
<p>For issues that start out as bugs, but later become features or feature changes, those issues would be tranferred into CommonRuby at the point where it's obvious they're feature-related.</p>
<ol start="3">
<li>Detriments</li>
</ol>
<p>Benefits are stated in the introduction above.</p>
<p>Possible detriments with mitigation:</p>
<ul>
<li>Confusion by users about where to file features.</li>
</ul>
<p>This would be mitigated by adding more information to bug-related home pages about the CommonRuby project. The "feature" value in current "trunk" project could either be removed (after migrating features to CommonRuby) or modified to error/warn or switch the issue to CommonRuby programmatically.</p>
<ul>
<li>More complex process.</li>
</ul>
<p>I believe this process is no more complicated than the current process. It also makes the process of evolving "common Ruby" more isolated from MRI development and may make it easier for users to track that evolution.</p>
<ol start="4">
<li>Further justification</li>
</ol>
<p>A lot of noise has been made over the past several months about Ruby lacking a process for new and changing features. The design process proposed by Brian Shirai (née Ford) gained some measure of popularity, but requires a complete retooling and reworking of current processes, making it infeasible for short-term implementation. Other process-change proposals have been kicked around on ruby-core, but the truth is that there <em>is</em> a current process, even if it's not particularly visible. By implementing my proposal, the process would become more obvious and transparent without major impact to MRI's development or Ruby's evolutionary processes.</p>
<ol start="5">
<li>Prior art</li>
</ol>
<p>The PEP (Python Enhancement Proposal) and JSR (Java Specification Request) processes are partial inspiration for this proposal. The latter governs all visible feature changes to Python independent of bug reports to the main "CPython" implementation. The latter governs (through a heavy and overly-strict process) changes to "Java" independent of individual JVM implementations. Both processes have been very successful at isolating spec changes from implementation changes, although the JSR process tends to move very slowly and be less transparent than it should be.</p>
<ol start="6">
<li>Conclusion</li>
</ol>
<p>Ruby does not lack a process for adding or changing features, but it does lack visibility into that process and in many cases fails to provide tools to non-MRI implementations to participate. Moving feature requests and discussion to a CommonRuby project independent of MRI will make the process more transparent and easier to follow (for users and implementers) while having minimal impact on the current process.</p> Ruby master - Feature #8263 (Assigned): Support discovering yield state of individual Fibershttps://bugs.ruby-lang.org/issues/82632013-04-13T11:18:49Zhalorgium (Tim Carey-Smith)ruby@spork.in
<p>Related to <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Support accessing Fiber-locals and backtraces for a Fiber (Closed)" href="https://bugs.ruby-lang.org/issues/8215">#8215</a>, when debugging a multi-Fiber application or library it is useful to be able to look at the stack for the <code>Thread</code> which is possible right now.<br>
Currently it is not possible to discover where the Fiber was yielded.</p>
<p>Is this something that could be added?</p>
<p><a href="https://gist.github.com/halorgium/f63abf177a96d7113ce3" class="external">Thread.backtrace example</a></p> Ruby master - Feature #8164 (Assigned): Public/Privatehttps://bugs.ruby-lang.org/issues/81642013-03-26T07:48:13ZAnonymous
<ul>
<li>#private<a href="http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-private" class="external">http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-private</a>
<ul>
<li>#private_class_method<a href="http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-private_class_method" class="external">http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-private_class_method</a>
</li>
<li>#public<a href="http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-public" class="external">http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-public</a>
</li>
<li>#public_class_method<a href="http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-public_class_method" class="external">http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-public_class_method</a>
</li>
</ul>
</li>
</ul>
<p>Would it be a good idea to compress these 4 methods to 2 methods?</p>
<p>public - Can set both instance <em>and</em> class methods to public by passing<br>
them in as symbol<br>
private - Can set both instance <em>and</em> class methods to private by passing<br>
them in as symbol</p>
<p>and enable them to be called at top of class? Is this a good idea? It would<br>
clean up Module# and encourage use of these two<br>
as methods rather than keywords</p> Ruby master - Bug #7968 (Assigned): Poor UDPSocket#send performance in ruby 2.0.0 on windowshttps://bugs.ruby-lang.org/issues/79682013-02-26T20:55:25Zcs96and (Alan Davies)alan.n.davies@gmail.com
<p>I have noticed that the performance of UDPSocket#send on ruby 2.0.0 on windows is much poorer than that of 1.9.3 or 1.8.7. Running the attahced script on 2.0.0 gives the following...</p>
<p>d:\scripts>bash -c "ruby --version"<br>
ruby 2.0.0p0 (2013-02-24) [x64-mingw32]</p>
<p>d:\scripts>bash -c "time ruby socketsendtest.rb"</p>
<p>real 0m2.572s<br>
user 0m0.000s<br>
sys 0m0.016s</p>
<p>However, running the same test with 1.9.3 is much faster...</p>
<p>d:\scripts>pik 193</p>
<p>d:\scripts>bash -c "ruby --version"<br>
ruby 1.9.3p374 (2013-01-15) [i386-mingw32]</p>
<p>d:\scripts>bash -c "time ruby socketsendtest.rb"</p>
<p>real 0m0.993s<br>
user 0m0.015s<br>
sys 0m0.016s</p>
<p>Additionally, if I change the send call to a print (commented out in the script), then the performance is fine on 2.0.0....</p>
<p>d:\scripts>pik 200</p>
<p>d:\scripts>bash -c "ruby --version"<br>
ruby 2.0.0p0 (2013-02-24) [x64-mingw32]</p>
<p>d:\scripts>bash -c "time ruby socketsendtest.rb"</p>
<p>real 0m0.907s<br>
user 0m0.000s<br>
sys 0m0.015s</p>
<p>What is send() doing that print() doesn't do that is causing the massive performance drop?</p>
<p>Thanks<br>
Alan.</p> Ruby master - Bug #7964 (Assigned): Writing an ASCII-8BIT String to a StringIO created from a UTF...https://bugs.ruby-lang.org/issues/79642013-02-26T16:32:50Zbrixen (Brian Shirai)brixen@gmail.com
<p>=begin<br>
In the following script, an ASCII-8BIT String is written to a StringIO created with a UTF-8 String without error. However, a << b or a + b will raise an exception, as will writing an ASCII-8BIT String to a File with UTF-8 external encoding.</p>
<ul>
<li>
<p>$ cat file_enc.rb</p>
<a name="encoding-utf-8"></a>
<h1 >encoding: utf-8<a href="#encoding-utf-8" class="wiki-anchor">¶</a></h1>
<p>require 'stringio'</p>
<p>a = "On a very cold morning, it was -8°F."<br>
b = a.dup.force_encoding "ascii-8bit"</p>
<p>io = StringIO.new a<br>
io.write(b)<br>
p io.string.encoding</p>
<p>File.open "data.txt", "w:utf-8" do |f|<br>
f.write a<br>
f.write b<br>
end</p>
</li>
<li>
<p>$ ruby2.0 -v file_enc.rb<br>
ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-darwin10.8.0]<br>
#<a href="Encoding:UTF-8" class="external">Encoding:UTF-8</a><br>
file_enc.rb:13:in <code>write': "\xC2" from ASCII-8BIT to UTF-8 (Encoding::UndefinedConversionError) from file_enc.rb:13:in </code>block in '<br>
from file_enc.rb:11:in <code>open' from file_enc.rb:11:in </code>'</p>
</li>
<li>
<p>$ ruby1.9.3 -v file_enc.rb<br>
ruby 1.9.3p327 (2012-11-10 revision 37606) [x86_64-darwin10.8.0]<br>
#<a href="Encoding:UTF-8" class="external">Encoding:UTF-8</a><br>
file_enc.rb:13:in <code>write': "\xC2" from ASCII-8BIT to UTF-8 (Encoding::UndefinedConversionError) from file_enc.rb:13:in </code>block in '<br>
from file_enc.rb:11:in <code>open' from file_enc.rb:11:in </code>'<br>
=end</p>
</li>
</ul> Ruby master - Feature #7580 (Assigned): Range translationhttps://bugs.ruby-lang.org/issues/75802012-12-17T14:43:24ZAnonymous
<p>=begin<br>
I would like to propose the (({#+})) and (({#-})) methods on (({Range})).</p>
<p>These would be useful for translating ranges - for example, given a range where the endpoints are 1-indexed, the range could be translated by 1 in the negative direction to use in (({Array#[]})).</p>
<p>Instead of doing a syntactically-bulky manual translation like so:</p>
<p>ary[(range.begin - 1)..(range.end - 1)]</p>
<p>(({Range#-})) could be used instead:</p>
<p>ary[range - 1]</p>
<p>The translation methods would not handle certain endpoint types specially, they would just pass the call on.</p>
<p>Here's an example implementation in Ruby:</p>
<p>class Range<br>
def +(other)<br>
Range.new(self.begin + other, self.end + other, exclude_end?)<br>
end</p>
<pre><code>def -(other)
Range.new(self.begin - other, self.end - other, exclude_end?)
end
</code></pre>
<p>end</p>
<p>=end</p> Ruby master - Feature #7488 (Assigned): Receiving object_id in object creation probeshttps://bugs.ruby-lang.org/issues/74882012-12-01T23:24:08ZauthorNari (Narihiro Nakamura)authorNari@gmail.com
<p>Hi.</p>
<p>I want to get a object id in object creation probes to know a creation<br>
point of a suspect object.</p>
<p>I've wrote a patch for above.<br>
<a href="https://gist.github.com/4182140" class="external">https://gist.github.com/4182140</a></p>
<p>Could you check it?</p>
<a name="Im-sorry-I-dont-have-a-Mac-so-I-do-not-execute-dtraces-tests"></a>
<h1 >I'm sorry, I don't have a Mac so I do not execute dtrace's tests...<a href="#Im-sorry-I-dont-have-a-Mac-so-I-do-not-execute-dtraces-tests" class="wiki-anchor">¶</a></h1>
<p>Thanks!</p> Ruby master - Feature #7412 (Assigned): Pathname#relative_path_from does not support mixed direct...https://bugs.ruby-lang.org/issues/74122012-11-20T20:15:24Z7er (Syver Enstad)syver.enstad@gmail.com
<p>=begin<br>
The support for mixing backslashes and forward slashes in the pathname module in the standard library seems to be broken on windows</p>
<pre><code>require 'pathname'
base = Pathname.new("c:\\")
filepath = Pathname.new("c:/foo/bar/file.ext")
base.relative_path_from(filepath)
</code></pre>
<p>raises <code>ArgumentError: different prefix: "c:\\" and "c:/foo/bar/file.ext"</code></p>
<p>Changing filepath to contain backslashes fixes the problem</p>
<pre><code>filepath = Pathname.new("c:\\foo\\bar\\file.ext")
base.relative_path_from(filepath)
</code></pre>
<p><code>=> #<Pathname:../../..></code><br>
=end</p> Ruby master - Feature #7349 (Assigned): Struct#inspect needs more meaningful outputhttps://bugs.ruby-lang.org/issues/73492012-11-14T11:32:05Zpostmodern (Hal Brodigan)postmodern.mod3@gmail.com
<p>When inheriting directly from Struct.new, Class#ancestors shows a meaningless anonymous Class:</p>
<pre><code>class Point < Struct.new(:x, :y)
def distance
((x ** 2) + (y ** 2)) ** 0.5
end
end
Point.ancestors
# => [Point, #<Class:0x007fe204a1a228>, Struct, Enumerable, Object, Kernel, BasicObject]
</code></pre>
<p>Perhaps, the anonymous Class could list the Struct's fields?</p>
<pre><code>#<Class:x, y>
</code></pre> Ruby master - Feature #6841 (Assigned): Shorthand for Assigning Return Value of Method to Selfhttps://bugs.ruby-lang.org/issues/68412012-08-07T11:37:53Zwardrop (Tom Wardrop)tom@tomwardrop.com
<p>=begin<br>
Quite often in Ruby, I find myself doing something like: (({my_var[:foo][:bar] = my_var[:foo][:bar].to_i})) or (({obj.foo.bar = obj.foo.bar.to_i})). Realising this, I thought of what would be a fairly nice shorthand syntax for this, which could be: (({my_var[:foo][:bar] .= to_i})). How this works should be pretty self-explanatory. The (({.=})) operator works exactly like any other assignment operator of this nature.</p>
<p>Would be nice to see this in Ruby 2.0. Wondering what others think of this?<br>
=end</p> Ruby master - Feature #6802 (Assigned): String#scan should have equivalent yielding MatchDatahttps://bugs.ruby-lang.org/issues/68022012-07-27T16:17:42Zprijutme4ty (Ilya Vorontsov)prijutme4ty@gmail.com
<p>Ruby should have method to obtain not an array of arrays but of MatchData objects. It can help in obtaining named groups:</p>
<p>pattern = /x: (?\d+) y:(?\d+)/<br>
polygon = []<br>
text.scan_for_pattern(pattern){|m| polygon << Point.new(m[:x], m[:y]) }</p>
<p>Not to break existing code we need unique name. Ideas? May be #each_match</p> Ruby master - Feature #6769 (Assigned): rbinstall.rb: install both src and batch files separetelyhttps://bugs.ruby-lang.org/issues/67692012-07-22T10:04:13Zluislavena (Luis Lavena)luislavena@gmail.com
<p>=begin<br>
Hello,</p>
<p>Current behavior of rbinstall.rb is to concat bin scripts (erb, rake, rdoc, etc) along with a batchfile stub in a single file, resulting in erb.bat, rdoc.bat etc.</p>
<p>Those files works OK when invoked directly, but they do not support the following scenarios:</p>
<ul>
<li>
<p>Invoke it like "ruby -S rake", which looks for extension-less script in the path (and that does not exist)</p>
</li>
<li>
<p>Cannot invoke those scripts from another script, example, from Rake, do "ruby 'rdoc'" will not work.</p>
</li>
</ul>
<p>To circumvent this issue at RubyInstaller, we copied the original bin scripts and replaced the batchfile stubs with simple ones:</p>
<p><a href="https://github.com/oneclick/rubyinstaller/blob/master/recipes/interpreter/ruby19.rake#L188-197" class="external">https://github.com/oneclick/rubyinstaller/blob/master/recipes/interpreter/ruby19.rake#L188-197</a></p>
<p>===</p>
<p>I would like to change rbinstall.rb to copy over verbatim bin scripts and simple batchfiles stubs.</p>
<p>That will solve the above two issues I mentioned plus open the scenario to a easy executable-based launcher, similar to gem-exefy:</p>
<p><a href="https://github.com/bosko/gem-exefy" class="external">https://github.com/bosko/gem-exefy</a></p>
<p>To have identifiable scripts in list of process plus, customized firewall rules and remove the dreaded "Terminate batch job" prompt.</p>
<p>Before I start working on this, I wanted to know what do you think about this?</p>
<p>Thanks in advance for your feedback and looking forward your responses.<br>
=end</p> Ruby master - Feature #6694 (Assigned): Thread.new without block.https://bugs.ruby-lang.org/issues/66942012-07-04T13:51:11Zko1 (Koichi Sasada)
<a name="Abstract"></a>
<h1 >Abstract<a href="#Abstract" class="wiki-anchor">¶</a></h1>
<p>Support Thread.new() without block.</p>
<p>Before: <code>Thread.new(params...){|thread_local_params| ...}</code></p>
<p>After: <code>Thread.new(proc: lambda{|tl_params...| ...}, args: params..., other_thread_config...)</code></p>
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p>Thread.new creates new Thread object and run passed block in another thread immediately. Thread.new can receive parameters and pass all parameters to block.</p>
<pre><code> Thread.new(a, b, c) do |ta, tb, tc|
# ta, tb, tc is thread local
}
</code></pre>
<p>There are some request to specify thread configurations such as stack size described in [Ruby 1.9 - Feature <a class="issue tracker-2 status-6 priority-4 priority-default closed" title="Feature: Allow dynamic Fiber stack size (Rejected)" href="https://bugs.ruby-lang.org/issues/3187">#3187</a>] (in this case, stack size for Fiber.new). However, we have no way to pass such thread configuration on the Thread.new().</p>
<a name="Proposal"></a>
<h1 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h1>
<p>Allow Thread.new() without block. A block will be passed with proc parameter. Passed arguments will be passed with args parameter.</p>
<pre><code> # ex1
Thread.new(){...}
#=>
Thread.new(proc: -> {...})
# ex2
Thread.new(a, b, c){|ta, tb, tc| ...}
#=>
Thread.new(proc: ->(ta, tb, tc){ ... }, params: [a, b, c])
</code></pre>
<p>If you want to specify stack size, then:</p>
<p>Thread.new(stack_size: 4096, proc: proc{...}, args: [a, b, c])</p>
<p>Note that I'll make another ticket for thread (and fiber) creation parameters.</p>
<p>This change can be described with the following pseudo code:</p>
<pre><code> def Thread.new(*args, &block)
if block
Thread.new_orig(*args, &block)
else
config = args[0] || raise ArgumentError
stack_size = config[:stack_size]
# ... and process another parameters
Thread.new_orig(*config[:args], &config[:proc])
end
end
</code></pre>
<a name="Another-proposal"></a>
<h1 >Another proposal<a href="#Another-proposal" class="wiki-anchor">¶</a></h1>
<p>On the <a href="/issues/3187">[ruby-core:43385]</a>, Nahi-san proposed that if no block given on Thread.new(), then create "waiting" thread. Thread#run kicks waiting thread with parameters.</p>
<pre><code> th = Thread.new(thread_config_params)
...
th.run(params){|thread_local_params|
...
}
</code></pre>
<p>We can combine with <code>proc:</code> parameter and this proposal.<br>
If <code>Thread.new()</code> doesn't have block and <code>proc:</code> parameter, then making a waiting thread.</p>
<p>NOTE: Because we have already Thread#run, Thread#start is better than Thread#run?</p>
<a name="Note"></a>
<h1 >Note<a href="#Note" class="wiki-anchor">¶</a></h1>
<p>I don't make any survey on other languages. Please give us your comments.</p> Ruby master - Feature #6648 (Assigned): Provide a standard API for retrieving all command-line fl...https://bugs.ruby-lang.org/issues/66482012-06-26T07:56:37Zheadius (Charles Nutter)headius@headius.com
<p>=begin<br>
Currently there are no standard mechanisms to get the flags passed to the currently running Ruby implementation. The available mechanisms are not ideal:</p>
<ul>
<li>Scanning globals and hoping they have not been tweaked to new settings</li>
<li>Using external wrappers to launch Ruby</li>
<li>???</li>
</ul>
<p>Inability to get the full set of command-line flags, including flags passed to the VM itself (and probably VM-specific) makes it impossible to launch subprocess Ruby instances with the same settings.</p>
<p>A real world example of this is "((%bundle exec%))" when called with a command line that sets various flags, a la ((%jruby -Xsome.vm.setting --1.9 -S bundle exec%)). None of these flags can propagate to the subprocess, so odd behaviors result. The only option is to put the flags into an env var (((|JRUBY_OPTS|)) or ((|RUBYOPT|))) but this breaks the flow of calling a simple command line.</p>
<p>JRuby provides mechanisms to get all its command line options, but they require calling Java APIs from Ruby's API set. Rubinius provides its own API for accessing comand-line options, but I do not know if it includes VM-level flags as well as standard Ruby flags.</p>
<p>I know there is a (({RubyVM})) namespace in the 2.0 line. If that namespace is intended to be general-purpose for VM-level features, it would be a good host for this API. Something like...</p>
<p>class << RubyVM<br>
def vm_args; end # returns array of command line args <em>not</em> passed to the target script</p>
<pre><code>def script; end # returns the script being executed...though this overlaps with $0
def script_args; end # returns args passed to the script...though this overlaps with ARGV, but that is perhaps warranted since ARGV can be modified (i.e. you probably want the original args)
</code></pre>
<p>end<br>
=end</p> Ruby master - Feature #6613 (Assigned): VT_RECORD, IRecordInfo Support in WIN32OLEhttps://bugs.ruby-lang.org/issues/66132012-06-21T07:54:17Zdsisnero (Dominic Sisneros)dsisnero@gmail.com
<p>WIN32OLE has no support for VT_RECORD VARIANTS. Python and Perl use the<br>
functions GetRecordInfoFromTypeInfo and GetRecordInfoFromGuids to add<br>
support for VT_RECORD and the IRecordInfo interface.</p>
<p>suggest having a class IRecordInfo and support for generating a Class<br>
for the UDT to use this Record/Struct in ruby</p>
<p>The method starting on 1395 needs a case statement for VT_RECORD and a way to turn that into a IRECORD class</p>
<p>static void *<br>
get_ptr_of_variant(VARIANT *pvar)<br>
{<br>
switch(V_VT(pvar)) {<br>
case VT_UI1:<br>
return &V_UI1(pvar);<br>
break;</p>
<p>The IDL definitions for the methods are as follows</p>
<p>HRESULT GetRecordInfoFromTypeInfo(<br>
__in ITypeInfo *pTypeInfo,<br>
__out IRecordInfo **ppRecInfo<br>
);</p>
<p>HRESULT GetRecordInfoFromGuids(<br>
__in REFGUID rGuidTypeLib,<br>
__in ULONG uVerMajor,<br>
__in ULONG uVerMinor,<br>
__in LCID lcid,<br>
__in REFGUID rGuidTypeInfo,<br>
__out IRecordInfo **ppRecInfo<br>
);</p>
<p>here is the CTYPES definition for python that adds this support</p>
<p>class IRecordInfo(IUnknown):<br>
# C:/vc98/include/OAIDL.H 5974<br>
<em>iid</em> = GUID("{0000002F-0000-0000-C000-000000000046}")</p>
<pre><code>def GetFieldNames(self, *args):
count = c_ulong()
self.__com_GetFieldNames(count, None)
array = (BSTR * count.value)()
self.__com_GetFieldNames(count, array)
result = array[:]
# XXX Should SysFreeString the array contents. How to?
return result
</code></pre>
<p>IRecordInfo. <em>methods</em> = [<br>
COMMETHOD([], HRESULT, 'RecordInit',<br>
(['in'], c_void_p, 'pvNew')),<br>
COMMETHOD([], HRESULT, 'RecordClear',<br>
(['in'], c_void_p, 'pvExisting')),<br>
COMMETHOD([], HRESULT, 'RecordCopy',<br>
(['in'], c_void_p, 'pvExisting'),<br>
(['in'], c_void_p, 'pvNew')),<br>
COMMETHOD([], HRESULT, 'GetGuid',<br>
(['out'], POINTER(GUID), 'pguid')),<br>
COMMETHOD([], HRESULT, 'GetName',<br>
(['out'], POINTER(BSTR), 'pbstrName')),<br>
COMMETHOD([], HRESULT, 'GetSize',<br>
(['out'], POINTER(c_ulong), 'pcbSize')),<br>
COMMETHOD([], HRESULT, 'GetTypeInfo',<br>
(['out'], POINTER(POINTER(ITypeInfo)), 'ppTypeInfo')),<br>
COMMETHOD([], HRESULT, 'GetField',<br>
(['in'], c_void_p, 'pvData'),<br>
(['in'], c_wchar_p, 'szFieldName'),<br>
(['out'], POINTER(VARIANT), 'pvarField')),<br>
COMMETHOD([], HRESULT, 'GetFieldNoCopy',<br>
(['in'], c_void_p, 'pvData'),<br>
(['in'], c_wchar_p, 'szFieldName'),<br>
(['out'], POINTER(VARIANT), 'pvarField'),<br>
(['out'], POINTER(c_void_p), 'ppvDataCArray')),<br>
COMMETHOD([], HRESULT, 'PutField',<br>
(['in'], c_ulong, 'wFlags'),<br>
(['in'], c_void_p, 'pvData'),<br>
(['in'], c_wchar_p, 'szFieldName'),<br>
(['in'], POINTER(VARIANT), 'pvarField')),<br>
COMMETHOD([], HRESULT, 'PutFieldNoCopy',<br>
(['in'], c_ulong, 'wFlags'),<br>
(['in'], c_void_p, 'pvData'),<br>
(['in'], c_wchar_p, 'szFieldName'),<br>
(['in'], POINTER(VARIANT), 'pvarField')),<br>
COMMETHOD([], HRESULT, 'GetFieldNames',<br>
(['in', 'out'], POINTER(c_ulong), 'pcNames'),<br>
(['in'], POINTER(BSTR), 'rgBstrNames')),<br>
COMMETHOD([], BOOL, 'IsMatchingType',<br>
(['in'], POINTER(IRecordInfo))),<br>
COMMETHOD([], HRESULT, 'RecordCreate'),<br>
COMMETHOD([], HRESULT, 'RecordCreateCopy',<br>
(['in'], c_void_p, 'pvSource'),<br>
(['out'], POINTER(c_void_p), 'ppvDest')),<br>
COMMETHOD([], HRESULT, 'RecordDestroy',<br>
(['in'], c_void_p, 'pvRecord'))]</p>
<p>################################################################</p>
<a name="functions"></a>
<h1 >functions<a href="#functions" class="wiki-anchor">¶</a></h1>
<p>_oleaut32 = oledll.oleaut32</p>
<p>def GetRecordInfoFromTypeInfo(tinfo):<br>
"Return an IRecordInfo pointer to the UDT described in tinfo"<br>
ri = POINTER(IRecordInfo)()<br>
_oleaut32.GetRecordInfoFromTypeInfo(tinfo, byref(ri))<br>
return ri</p>
<p>def GetRecordInfoFromGuids(rGuidTypeLib, verMajor, verMinor, lcid,<br>
rGuidTypeInfo):<br>
ri = POINTER(IRecordInfo)()<br>
_oleaut32.GetRecordInfoFromGuids(byref(GUID(rGuidTypeLib)),<br>
verMajor, verMinor, lcid,<br>
byref(GUID(rGuidTypeInfo)),<br>
byref(ri))<br>
return ri</p> Ruby master - Feature #6445 (Assigned): request for default length/position on string indexhttps://bugs.ruby-lang.org/issues/64452012-05-17T13:02:30Zbotp (bot pena)botpena@gmail.com
<p>would be nice if ruby has default for "rest or up to end of string"</p>
<p>eg</p>
<p>"hello"[2,] => should default to "hello"[2..-1]<br>
or<br>
"hello"[2..] => should default to "hello"[2..-1]</p> Ruby master - Feature #6354 (Assigned): Remove escape (break/return/redo/next support) from class...https://bugs.ruby-lang.org/issues/63542012-04-25T12:12:17Zko1 (Koichi Sasada)
<p>Let's remove global escape (break/return/redo/next support) from class/module scope.</p>
<p>Yes, it introduces incompatibility. However, anyone use it?<br>
I think the following examples are evil (difficult to understand).</p>
<a name="examples"></a>
<h1 >examples:<a href="#examples" class="wiki-anchor">¶</a></h1>
<p>1.times{<br>
class C<br>
break # break from 1.times<br>
end<br>
}</p>
<p>1.times{<br>
class C<br>
module M<br>
break # break from 1.times<br>
end<br>
end<br>
}</p>
<p>3.times{|n|<br>
p n # repeat print 0<br>
class C<br>
redo<br>
end<br>
}</p>
<p>->{<br>
class C<br>
return return from outer lambda block<br>
end<br>
}.call</p>
<p>->{<br>
proc{<br>
class C<br>
return # return from outer lambda (not proc) block<br>
end<br>
}.call<br>
}.call</p>
<p>etc, etc.</p> Ruby master - Bug #6351 (Assigned): transcode table generator does not support multi characters o...https://bugs.ruby-lang.org/issues/63512012-04-24T20:41:39Zusa (Usaku NAKAMURA)usa@garbagecollect.jp
<p>改めてチケット起こします。<a href="/issues/6349">[ruby-dev:45576]</a> より。</p>
<p>On 2012/04/24 17:11, "Martin J. Dürst" wrote:</p>
<blockquote>
<p>On 2012/04/24 17:02, U.Nakamura wrote:</p>
<blockquote>
<p>データは例によってNetBSDのものが利用できそうです。<br>
なのですが、transcodeってUnicodeの第0面(BMP)以外はサポートし<br>
てましたっけ?</p>
</blockquote>
<p>もちろんです :-)</p>
</blockquote>
<p>もうちょっと調べました。BMP 以外は transcode の最初から全く問題ないです<br>
が、現時点で引っかかるのは次のものです<br>
(<a href="http://x0213.org/codetable/euc-jis-2004-std.txt" class="external">http://x0213.org/codetable/euc-jis-2004-std.txt</a> から抜粋):</p>
<p>0xA4F7 U+304B+309A # [2000]<br>
0xA4F8 U+304D+309A # [2000]<br>
0xA4F9 U+304F+309A # [2000]<br>
0xA4FA U+3051+309A # [2000]<br>
0xA4FB U+3053+309A # [2000]</p>
<p>0xA5F7 U+30AB+309A # [2000]<br>
0xA5F8 U+30AD+309A # [2000]<br>
0xA5F9 U+30AF+309A # [2000]<br>
0xA5FA U+30B1+309A # [2000]<br>
0xA5FB U+30B3+309A # [2000]<br>
0xA5FC U+30BB+309A # [2000]<br>
0xA5FD U+30C4+309A # [2000]<br>
0xA5FE U+30C8+309A # [2000]</p>
<p>0xA6F8 U+31F7+309A # [2000]</p>
<p>0xABC4 U+00E6+0300 # [2000]</p>
<p>0xABC8 U+0254+0300 # [2000]<br>
0xABC9 U+0254+0301 # [2000]<br>
0xABCA U+028C+0300 # [2000]<br>
0xABCB U+028C+0301 # [2000]<br>
0xABCC U+0259+0300 # [2000]<br>
0xABCD U+0259+0301 # [2000]<br>
0xABCE U+025A+0300 # [2000]<br>
0xABCF U+025A+0301 # [2000]</p>
<p>0xABE5 U+02E9+02E5 # [2000]<br>
0xABE6 U+02E5+02E9 # [2000]</p>
<p>ようするに、JIS X 0213 で一文字になっているが、Unicode で二文字になって<br>
いるものです。EUC-JISX0213 から UTF-8 は問題ないですが、逆は現在引っかか<br>
ります。windows-1258 も (逆ですが) 同じ問題がありますので、いずれはなく<br>
さないといけないと思いましたが、今回はいいきっかけのではないかと思います。</p>
<p>よろしくお願いします。 Martin.</p> Ruby master - Feature #6317 (Assigned): Range#cover?の引数としてRangeインスタンスを受けられるようにして欲しいhttps://bugs.ruby-lang.org/issues/63172012-04-18T20:51:08Zmasaakiaoyagi (Masaaki Aoyagi)masaaki.aoyagi@gmail.com
<p>青柳と申します。</p>
<p>以下のように、Range#cover?の引数としてRangeインスタンスを<br>
受けられるようにして欲しいです。<br>
(1..4).cover?(2..3) # => true<br>
(1..4).cover?(0..3) # => false</p>
<p>取り敢えず実装してみましたので、添付いたします。</p> Ruby master - Feature #6265 (Assigned): Remove 'useless' 'concatenation' syntaxhttps://bugs.ruby-lang.org/issues/62652012-04-06T21:53:53Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<p>What is wrong with this code:</p>
<p>some_method 'argument1', 'argument2' 'argument3'</p>
<p>Yes, the missing colon, but it is not always easy to notice that...</p>
<p>What is this ('concatenation' 'syntax') useful for?</p>
<p>Why writing ('some ' 'concatenation') instead of 'some concatenation'?</p>
<p>A missing colon between string arguments can lead to some bugs that may be hard to find, specially if the arguments are optional.</p>
<p>And I can't see any useful case where this allowed syntax for concatenation would help.</p> Ruby master - Feature #6133 (Assigned): SSLSocketをshutdownできないhttps://bugs.ruby-lang.org/issues/61332012-03-13T00:17:22Zkik (Masashi Kikuchi)kik314@gmail.com
<p><a href="http://www.openssl.org/docs/ssl/SSL_shutdown.html" class="external">http://www.openssl.org/docs/ssl/SSL_shutdown.html</a><br>
に対応するメソッドがないので、送信の終わりを送れません。ただし微妙にshutdown(2)とインターフェースが違ってます。</p> Ruby master - Feature #6012 (Assigned): Proc#source_location also return the columnhttps://bugs.ruby-lang.org/issues/60122012-02-14T09:17:30Zrogerdpack (Roger Pack)rogerpack2005@gmail.com
<p>As originally suggested in <a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/42418" class="external">http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/42418</a></p>
<p>Suggestion/feature request:<br>
have #source_location also return the beginning column where it was defined.<br>
["test.rb", 8, 33]</p>
<p>Thanks!<br>
-roger-</p> Ruby master - Feature #5825 (Assigned): Sweet instance var assignment in the object initializerhttps://bugs.ruby-lang.org/issues/58252011-12-30T22:49:03Zgoshakkk (Gosha Arinich)me@goshakkk.name
<p>I'm very excited about this feature in CoffeeScript, and think it might be a nice-to-have thing in Ruby 2.0.</p>
<p>That's how I think it would look like:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Me</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="vi">@name</span><span class="p">,</span> <span class="vi">@age</span><span class="p">,</span> <span class="vi">@location</span><span class="p">);</span> <span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>So we can declare <code>@variable</code>s in the initializer method parameters definition to avoid assigning instance variables from method arguments by hand, like:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Me</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="n">age</span><span class="p">,</span> <span class="n">location</span><span class="p">)</span>
<span class="vi">@name</span> <span class="o">=</span> <span class="nb">name</span>
<span class="vi">@age</span> <span class="o">=</span> <span class="n">age</span>
<span class="vi">@location</span> <span class="o">=</span> <span class="n">location</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>Want to hear what do you guys think, does that feature worth being included in 2.0?</p> Ruby master - Feature #5781 (Assigned): Query attributes (attribute methods ending in `?` mark)https://bugs.ruby-lang.org/issues/57812011-12-20T04:57:11Ztrans (Thomas Sawyer)
<p>Pretty sure this has come up before, but I'd like to revisit b/c I don't understand why it isn't allowed.</p>
<p>Sometimes I define "query" attributes, and in those cases I'd like the reader method to end in a <code>?</code> mark. Currently I have to do:</p>
<pre><code># @attribute
def foo?
@foo
end
</code></pre>
<p>or, if I don't mind a shadowing bare method,</p>
<pre><code>attr :foo
alias_method :foo?, :foo
</code></pre>
<p>So why not just allow:</p>
<pre><code>attr :foo?
</code></pre>
<p>Currently this causes an error. But why? It just seems like a waste of potentially cleaner code.</p> Ruby master - Feature #5741 (Assigned): Secure Erasure of Passwordshttps://bugs.ruby-lang.org/issues/57412011-12-11T06:02:13ZMartinBosslet (Martin Bosslet)Martin.Bosslet@gmail.com
<p>In other languages it is considered good practice to securely erase<br>
passwords immediately after they were used. Imagine authentication<br>
in a web app - ultimately a String containing the password arrives<br>
at the server, where it will be processed and compared to some<br>
previously stored value. After this is done, there is no need to<br>
store these password Strings any longer, so they should be<br>
discarded right away (more on why later).</p>
<p>In C, you would simply overwrite the array of bytes with zeroes or<br>
random values. In Java, Strings are immutable, that's why there it<br>
is common practice to use char[] for all things password and overwrite<br>
them when done.</p>
<p>Currently, there is no way in Ruby to overwrite the memory that<br>
was used by a String. String#clear and String#replace both use<br>
str_discard internally, which only frees the underlying pointer<br>
without overwriting it.</p>
<p>The problem with not erasing passwords is this: the contents of the<br>
String stay in memory until they are finally GC'ed. But even then<br>
only the pointer will be freed, leaving the contents mostly intact<br>
until the memory is reclaimed and overwritten later on.</p>
<p>This could be exploited if an attacker had access to the memory of<br>
the server. This could happen in many ways: a core dump after a<br>
crash, access to the host if the server runs in a VM, or even by<br>
deep-freezing the DRAM :) [1]</p>
<p>It could be argued that given the examples above, much more<br>
devastating attacks would be possible since in all of those<br>
cases you more or less have physical access to the machine. But<br>
I would still consider this to be a valid concern, if not only<br>
for the reason of never opening additional attack surfaces if<br>
they can be avoided relatively easily.</p>
<p>I also found [2], which seems to show that Python deals with<br>
similar problems and it also contains more background info.</p>
<p>Eric Hodel and I discussed this yesterday and Eric came up with<br>
a C extension that can be used to illustrate the problem (attached).</p>
<p>If you inspect the resulting core dump, you will find the following:</p>
<ul>
<li>the untouched String remains in memory fully intact</li>
<li>the String#clear'ed String remains to a large extent, typically the<br>
first character is missing - so if you typed "PASSWORD", search for<br>
"ASSWORD" (unintentional pun) instead</li>
<li>The String#clear_secure'ed will have been completely erased, no<br>
traces remain</li>
</ul>
<p>My questions:</p>
<ol>
<li>Would you agree that we need this functionality?</li>
<li>Where would we ideally place it? I'm not sure whether<br>
String is the perfect place, but on the other hand, String<br>
is the only place where we have access to the implementation<br>
details.</li>
<li>Are there better alternative ways how we could achieve this?</li>
</ol>
<p>[1] <a href="http://www.schneier.com/blog/archives/2008/02/cold_boot_attac.html" class="external">http://www.schneier.com/blog/archives/2008/02/cold_boot_attac.html</a><br>
[2] <a href="http://stackoverflow.com/questions/728164/securely-erasing-password-in-memory-python" class="external">http://stackoverflow.com/questions/728164/securely-erasing-password-in-memory-python</a></p> Ruby master - Feature #5643 (Assigned): require/load options and binding optionhttps://bugs.ruby-lang.org/issues/56432011-11-17T07:41:01Ztrans (Thomas Sawyer)
<p>Current Kernel#load is defined as:</p>
<pre><code>load(filename, wrap=false)
</code></pre>
<p>I purpose that it be modified to work as option argument, e.g.</p>
<pre><code>load(filename, :wrap=>true)
</code></pre>
<p>Right off the bat this has better name connascence.</p>
<p>Then support an additional option <code>:binding</code>, such that, given:</p>
<pre><code>$ cat lib/example.rb
def a
1
end
</code></pre>
<p>then</p>
<pre><code>class X
load('example.rb', :binding=>binding)
end
X.new.a #=> 1
</code></pre>
<p>The binding option should also work with #require (which would also support option parameter) differing from #load in the it would only allow the feature to be loaded once per-binding's self regardless of being required again.</p>
<p>This ability would greatly benefit systems that need "plugin" capability. Presently, a great deal of coding has to go into simulating this functionality to create plugin systems, which are often imperfect nor robust.</p> Ruby master - Feature #5558 (Assigned): String#% strange arity errorshttps://bugs.ruby-lang.org/issues/55582011-11-03T10:25:55Ztrans (Thomas Sawyer)
<p>When the number of arguments do not match the number of % parameters, the String#% method has some odd behavior.</p>
<p>When too many, it seems to work fine, ignoring the extra arguments.</p>
<p>"%s" % [1,2] #=> "1"</p>
<p>But if <code>$DEBUG = true</code>,</p>
<p>"%s" % [1,2] #=> ArgumentError: too many arguments for format string</p>
<p>That doesn't seem right. Is it an error or isn't it?</p>
<p>For too few arguments it is always an error:</p>
<p>"%s" % [] #=> ArgumentError: too few arguments</p>
<p>Personally, I think it should use '' for missing arguments. That would make it more flexible in practice.</p>
<p>I consider the first $DEBUG issue a bug, and the later a feature. But I'll just call it a feature altogether to make things easier.</p> Ruby master - Feature #5007 (Assigned): Proc#call_under: Unifying instance_eval and instance_exechttps://bugs.ruby-lang.org/issues/50072011-07-09T23:26:49Zjudofyr (Magnus Holm)judofyr@gmail.com
<p>I'm proposing a method called <code>Proc#call_under</code> (the name could be<br>
discussed) which both unifies <code>instance_eval</code> and <code>instance_exec</code>, and makes<br>
it possible to call a <code>Proc</code> with a block and a scope:</p>
<p><code>Proc#call_under(self, *args, &blk)</code>:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">proc</span> <span class="p">{</span> <span class="nb">self</span> <span class="p">}.</span><span class="nf">call_under</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># => 1</span>
<span class="nb">proc</span> <span class="p">{</span> <span class="o">|</span><span class="n">a</span><span class="o">|</span> <span class="nb">self</span> <span class="o">+</span> <span class="n">a</span> <span class="p">}.</span><span class="nf">call_under</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="c1"># => 3</span>
<span class="nb">proc</span> <span class="p">{</span> <span class="o">|&</span><span class="n">b</span><span class="o">|</span> <span class="nb">self</span> <span class="o">+</span> <span class="n">b</span><span class="p">.</span><span class="nf">call</span> <span class="p">}.</span><span class="nf">call_under</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="p">{</span> <span class="mi">2</span> <span class="p">}</span> <span class="c1"># => 4</span>
</code></pre> Ruby master - Feature #4824 (Assigned): Provide method Kernel#executed?https://bugs.ruby-lang.org/issues/48242011-06-04T19:59:21Zlazaridis.com (Lazaridis Ilias)ilias@lazaridis.com
<p>The current construct to execute main code looks not very elegant:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">if</span> <span class="kp">__FILE__</span> <span class="o">==</span> <span class="vg">$0</span>
<span class="n">my_main</span><span class="p">()</span> <span class="c1"># call any method or execute any code</span>
<span class="k">end</span>
</code></pre>
<p>With a <code>Kernel#executed?</code> method, this would become more elegant:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">if</span> <span class="n">executed?</span>
<span class="c1">#do this</span>
<span class="c1">#do that</span>
<span class="n">my_main</span><span class="p">()</span>
<span class="k">end</span>
</code></pre>
<p>or</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">main</span><span class="p">()</span> <span class="k">if</span> <span class="n">executed?</span>
</code></pre>
<p>This addition would not break any existent behaviour.</p> Ruby master - Feature #4592 (Assigned): Tempfileを直接保存したいhttps://bugs.ruby-lang.org/issues/45922011-04-21T16:43:31Zxibbar (Takeyuki FUJIOKA)xibbar@gmail.com
<p>=begin<br>
Tempfileは一時ファイルなので、プロセスが消えたり、#closeすると、<br>
ファイルが消えてしまいます。<br>
Tempfileのデータを保存するために<br>
一旦読みだして、書き込み用に別ファイルを開いて、<br>
そこに書きこまなければいけません。<br>
これが小さいファイルだったらいいのですが、<br>
大きいファイルになると、<br>
Tempfile#save みたいなメソッドを用意して、<br>
closeと同時に保存ができると、<br>
読みだして書きこむという無駄をなくすことができます。<br>
10MB程度だったらいいのですが、500MとかのTempfileだと<br>
かなり有効なメソッドだと思います。</p>
<p>#save とか #save! とか、何がいいかは議論の余地があると思います。<br>
=end</p> Ruby master - Feature #3953 (Assigned): TCPSocket / UDPSocket do not accept IPAddr objects.https://bugs.ruby-lang.org/issues/39532010-10-16T20:41:59Zpostmodern (Hal Brodigan)postmodern.mod3@gmail.com
<p>=begin<br>
I noticed that TCPSocket/UDPSocket only accept String IPs/Hostnames, but not IPAddr objects. This is counter-intuitive since IP Addresses, along with Hostnames, are used to connect/bind to sockets.</p>
<pre><code> require 'socket'
require 'resolv'
ip = IPAddr.new(Resolv.getaddress('www.example.com'))
sock = TCPSocket.new(ip,80)
TypeError: can't convert IPAddr into String
from (irb):5:in `initialize'
from (irb):5:in `new'
from (irb):5
</code></pre>
<p>=end</p> Ruby master - Feature #1644 (Assigned): recv on inherited socket wrapped in TCPSocket does not re...https://bugs.ruby-lang.org/issues/16442009-06-17T14:37:54Zkntuaf (Kedar H)knutaf@gmail.com
<p>=begin<br>
On Windows, if you try to wrap an existing winsock socket that was inherited from a parent process into a TCPSocket, any calls to recv on this socket in the child process will not retrieve any data.</p>
<p>This is because the inherited socket is not a member of the internal "socklist" structure in win32.c. rb_w32_select filters out all sockets that are not in this internal list, prior to calling ws2_32!select.</p>
<p>One good solution is for TCPSocket.for_fd to make sure to insert its argument into the socklist structure so that subsequent Winsock functions wrapped by Ruby will work as though the socket were created by this Ruby process. Another possible solution is to expose another method, something like TCPSocket.from_new_fd.<br>
=end</p>