Ruby Issue Tracking System: Issueshttps://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112023-08-02T05:08:15ZRuby Issue Tracking System
Redmine 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> Ruby master - Feature #19465 (Assigned): [PATCH] reuse open(2) from rb_file_load_ok on POSIX-like...https://bugs.ruby-lang.org/issues/194652023-02-25T01:48:35Znormalperson (Eric Wong)normalperson@yhbt.net
<pre><code>When loading Ruby source files, we can save the result of
successful opens as open(2)/openat(2) are a fairly expensive
syscalls. This also avoids a time-of-check-to-time-of-use
(TOCTTOU) problem.
This reduces open(2) syscalls during `require'; but should be
most apparent when users have a small $LOAD_PATH. Users with
large $LOAD_PATH will benefit less since there'll be more
open(2) failures due to ENOENT.
With `strace -c -e openat ruby -e exit' under Linux, this
results in a ~14% reduction of openat(2) syscalls
(glibc uses openat(2) to implement open(2)).
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
0.00 0.000000 0 296 110 openat
0.00 0.000000 0 254 110 openat
Additionally, the introduction of `struct ruby_file_load_state'
may make future optimizations more apparent.
This change cannot benefit binary (.so) loading since the
dlopen(3) API requires a filename and I'm not aware of an
alternative that takes a pre-existing FD. In typical
situations, Ruby source files outnumber the mount of .so
files.
I've only tested this lightly on small apps since I don't have
large codebases to test on. However, I think organizing various
on-stack variables into `struct ruby_file_load_state' can be
beneficial if we end up using io-uring on Linux.
</code></pre> Ruby master - Feature #19193 (Assigned): drop DOS TEXT mode supporthttps://bugs.ruby-lang.org/issues/191932022-12-09T16:38:20ZYO4 (Yoshinao Muramatsu)
<p>On Windows platform, <code>File.open(path, "r")</code> returns an object different from "rt" and "rb". I call that DOS TEXT mode here.</p>
<p>DOS TEXT mode does</p>
<ul>
<li>crlf conversion</li>
<li>0x1a treated EOF charactor on read</li>
</ul>
<p>and others (see Bug <a class="issue tracker-1 status-1 priority-4 priority-default" title="Bug: IO has third data mode, document is incomplete. (Open)" href="https://bugs.ruby-lang.org/issues/19192">#19192</a>).<br>
But DOS TEXT mode is almost unnecessary today and it seems to introduce lot of code complexities.</p>
<p>Now there is less need for dos text mode</p>
<ul>
<li>Microsoft's most apps works without CRLF newline.</li>
<li>Creating a crlf text file today should be explicit. (but that is default mode on windows now)</li>
<li>Interpreting EOF charactor can cause trouble.</li>
</ul>
<p>I think it's time to consider dropping DOS TEXT mode.<br>
What challenges are there and what preparation is needed?</p> Ruby master - Bug #18677 (Assigned): BigDecimal#power (**) returns FloatDomainError when passing ...https://bugs.ruby-lang.org/issues/186772022-04-04T09:27:59Zdorianmariefr (Dorian Marié)
<p>Example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">></span> <span class="no">BigDecimal</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="o">**</span> <span class="no">BigDecimal</span><span class="p">(</span><span class="s2">"Infinity"</span><span class="p">)</span>
<span class="no">FloatDomainError</span><span class="p">:</span> <span class="no">Computation</span> <span class="n">results</span> <span class="k">in</span> <span class="s1">'Infinity'</span>
</code></pre>
<p>Maybe:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s2">"bigdecimal/util"</span>
<span class="k">class</span> <span class="nc">BigDecimal</span> <span class="o"><</span> <span class="no">Numeric</span>
<span class="k">def</span> <span class="nf">**</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="k">if</span> <span class="n">other</span><span class="p">.</span><span class="nf">infinite?</span> <span class="o">==</span> <span class="mi">1</span>
<span class="k">if</span> <span class="nb">self</span> <span class="o">></span> <span class="mi">1</span>
<span class="no">BigDecimal</span><span class="o">::</span><span class="no">INFINITY</span>
<span class="k">elsif</span> <span class="nb">self</span> <span class="o">==</span> <span class="mi">1</span>
<span class="nb">self</span>
<span class="k">elsif</span> <span class="nb">self</span> <span class="o">>=</span> <span class="mi">0</span>
<span class="no">BigDecimal</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">else</span>
<span class="n">power</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">else</span>
<span class="n">power</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">puts_and_eval</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
<span class="nb">puts</span> <span class="n">string</span>
<span class="nb">p</span> <span class="nb">eval</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">puts_and_eval</span> <span class="s2">"10 ** BigDecimal::INFINITY"</span>
<span class="n">puts_and_eval</span> <span class="s2">"1 ** BigDecimal::INFINITY"</span>
<span class="n">puts_and_eval</span> <span class="s2">"0.1 ** BigDecimal::INFINITY"</span>
<span class="n">puts_and_eval</span> <span class="s2">"0 ** BigDecimal::INFINITY"</span>
<span class="n">puts_and_eval</span> <span class="s2">"-1 ** BigDecimal::INFINITY"</span>
</code></pre>
<p>Seems like ruby is doing very different things from math though</p> Ruby master - 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 - 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 - Bug #17578 (Assigned): mkmf experimental C++ Supporthttps://bugs.ruby-lang.org/issues/175782021-01-25T06:26:31Zcfis (Charlie Savage)
<p>I've been working on the Rice gem (<a href="https://github.com/jasonroelofs/rice" class="external">https://github.com/jasonroelofs/rice</a>) that wraps C++ code for use in Ruby.</p>
<p>I noticed that some c++ support was added to mkmf for Ruby 2.7. However, if I try to use it find a header it fails to work. For example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">find_header</span><span class="p">(</span><span class="s1">'rice.hpp'</span><span class="p">)</span>
</code></pre>
<p>The reason is the conftest uses gcc -E instead of g++ -E. To fix that requires overlading the cpp_command to support C++.</p>
<p>This the fix I have put in that works:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">MakeMakefile</span><span class="p">[</span><span class="s1">'C++'</span><span class="p">].</span><span class="nf">module_eval</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">cpp_command</span><span class="p">(</span><span class="n">outfile</span><span class="p">,</span> <span class="n">opt</span><span class="o">=</span><span class="s2">""</span><span class="p">)</span>
<span class="n">conf</span> <span class="o">=</span> <span class="n">cc_config</span><span class="p">(</span><span class="n">opt</span><span class="p">)</span>
<span class="k">if</span> <span class="vg">$universal</span> <span class="ow">and</span> <span class="p">(</span><span class="n">arch_flag</span> <span class="o">=</span> <span class="n">conf</span><span class="p">[</span><span class="s1">'ARCH_FLAG'</span><span class="p">])</span> <span class="ow">and</span> <span class="o">!</span><span class="n">arch_flag</span><span class="p">.</span><span class="nf">empty?</span>
<span class="n">conf</span><span class="p">[</span><span class="s1">'ARCH_FLAG'</span><span class="p">]</span> <span class="o">=</span> <span class="n">arch_flag</span><span class="p">.</span><span class="nf">gsub</span><span class="p">(</span><span class="sr">/(?:\G|\s)-arch\s+\S+/</span><span class="p">,</span> <span class="s1">''</span><span class="p">)</span>
<span class="k">end</span>
<span class="no">RbConfig</span><span class="o">::</span><span class="n">expand</span><span class="p">(</span><span class="s2">"$(CXX) -E </span><span class="si">#$INCFLAGS</span><span class="s2"> </span><span class="si">#$CPPFLAGS</span><span class="s2"> </span><span class="si">#$CFLAGS</span><span class="s2"> </span><span class="si">#{</span><span class="n">opt</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="no">CONFTEST_CXX</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">outfile</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span>
<span class="n">conf</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>The two changes over the default method are:</p>
<p>$(CC) -> $(CXX) -E<br>
#{CONFTEST_c} -> #{CONFTEST_cxx}</p>
<p>Could this change be merged in? I can provide a patch file if you would like.</p>
<p>Last, it wasn't obvious to me how to activate the C++ support in mkfm. I ended up doing this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="kp">include</span> <span class="no">MakeMakefile</span><span class="p">[</span><span class="s1">'C++'</span><span class="p">]</span>
</code></pre>
<p>Is that correct?</p> Ruby master - 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 #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 - Feature #17111 (Assigned): Improve performance of Net::HTTPHeader#set_form by 40%https://bugs.ruby-lang.org/issues/171112020-08-10T04:09:30Ztonytonyjan (Weihang Jian)tonytonyjan@gmail.com
<a name="diff"></a>
<h2 >diff<a href="#diff" class="wiki-anchor">¶</a></h2>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/lib/net/http/header.rb b/lib/net/http/header.rb
index a8901e7..3f1a008 100644
</span><span class="gd">--- a/lib/net/http/header.rb
</span><span class="gi">+++ b/lib/net/http/header.rb
</span><span class="p">@@ -475,9 +475,8 @@</span> def set_form(params, enctype='application/x-www-form-urlencoded', formopt={})
@body = nil
@body_stream = nil
@form_option = formopt
<span class="gd">- case enctype
- when /\Aapplication\/x-www-form-urlencoded\z/i,
- /\Amultipart\/form-data\z/i
</span><span class="gi">+ case enctype.downcase
+ when 'application/x-www-form-urlencoded', 'multipart/form-data'
</span> self.content_type = enctype
else
raise ArgumentError, "invalid enctype: #{enctype}"
</code></pre>
<a name="benchmark"></a>
<h2 >benchmark<a href="#benchmark" class="wiki-anchor">¶</a></h2>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'benchmark'</span>
<span class="nb">require</span> <span class="s1">'net/http'</span>
<span class="k">module</span> <span class="nn">Net::HTTPHeader</span>
<span class="k">def</span> <span class="nf">set_form2</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="n">enctype</span> <span class="o">=</span> <span class="s1">'application/x-www-form-urlencoded'</span><span class="p">,</span> <span class="n">formopt</span> <span class="o">=</span> <span class="p">{})</span>
<span class="vi">@body_data</span> <span class="o">=</span> <span class="n">params</span>
<span class="vi">@body</span> <span class="o">=</span> <span class="kp">nil</span>
<span class="vi">@body_stream</span> <span class="o">=</span> <span class="kp">nil</span>
<span class="vi">@form_option</span> <span class="o">=</span> <span class="n">formopt</span>
<span class="k">case</span> <span class="n">enctype</span><span class="p">.</span><span class="nf">downcase</span>
<span class="k">when</span> <span class="s1">'application/x-www-form-urlencoded'</span><span class="p">,</span> <span class="s1">'multipart/form-data'</span>
<span class="nb">self</span><span class="p">.</span><span class="nf">content_type</span> <span class="o">=</span> <span class="n">enctype</span>
<span class="k">else</span>
<span class="k">raise</span> <span class="no">ArgumentError</span><span class="p">,</span> <span class="s2">"invalid enctype: </span><span class="si">#{</span><span class="n">enctype</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">500_000</span>
<span class="n">request</span> <span class="o">=</span> <span class="no">Net</span><span class="o">::</span><span class="no">HTTP</span><span class="o">::</span><span class="no">Post</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'/'</span><span class="p">)</span>
<span class="no">Benchmark</span><span class="p">.</span><span class="nf">bm</span> <span class="k">do</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span>
<span class="no">GC</span><span class="p">.</span><span class="nf">disable</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span> <span class="p">{</span> <span class="n">n</span><span class="p">.</span><span class="nf">times</span> <span class="p">{</span> <span class="n">request</span><span class="p">.</span><span class="nf">set_form</span> <span class="p">[]</span> <span class="p">}</span> <span class="p">}</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span> <span class="p">{</span> <span class="n">n</span><span class="p">.</span><span class="nf">times</span> <span class="p">{</span> <span class="n">request</span><span class="p">.</span><span class="nf">set_form2</span> <span class="p">[]</span> <span class="p">}</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<pre><code> user system total real
0.777054 0.101768 0.878822 ( 0.880472)
0.539860 0.088957 0.628817 ( 0.630178)
</code></pre>
<p>I don't see any test for <code>#set_form</code> in <code>test/net/http/test_httpheader.rb</code>, let me know if I need to add more tests, thanks!</p> Ruby master - Misc #16805 (Assigned): Coroutine's license is unclearhttps://bugs.ruby-lang.org/issues/168052020-04-21T10:23:49Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<p>Files under <code>coroutine/</code> start like this:</p>
<pre><code class="C syntaxhl" data-language="C"><span class="o">/*</span>
<span class="o">*</span> <span class="n">This</span> <span class="n">file</span> <span class="n">is</span> <span class="n">part</span> <span class="n">of</span> <span class="n">the</span> <span class="s">"Coroutine"</span> <span class="n">project</span> <span class="n">and</span> <span class="n">released</span> <span class="n">under</span> <span class="n">the</span> <span class="n">MIT</span> <span class="n">License</span><span class="p">.</span>
<span class="o">*</span>
</code></pre>
<p>The problem is, there is no definition of "the MIT License" throughout the entire project.</p>
<p><a class="user active user-mention" href="https://bugs.ruby-lang.org/users/3344">@ioquatix (Samuel Williams)</a> can you add your terms somewhere inside of LEGAL? There are several other materials also under the MIT license. You can follow how they are listed up.</p> Ruby master - 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 #16350 (Assigned): ArithmeticSequence#member? can result in infinite loophttps://bugs.ruby-lang.org/issues/163502019-11-16T17:20:32Zparker (Parker Finch)
<p>I'm not sure if this is a bug or a feature, it feels somewhere in between.</p>
<p>This is my first time contributing to the Ruby code, let me know what I can improve in this report!</p>
<p>ArithmeticSequence#member? enumerates through the sequence in order to determine if an element is included. (It just uses Enumerable#member?.) This leads to an infinite loop if the sequence is infinite and the element is not included, such as <code>1.step.member?(0)</code>.</p>
<p>I expected <code>1.step.member?(0)</code> to return <code>false</code>.</p>
<p>Since ArithmeticSequences are much more constrained than regular Enumerables, the #member? method can be overridden to efficiently determine if an element is included in the sequence.</p>
<p>I started implementing this change (patch attached) but got a little confused when trying to handle floats. Before digging in too deeply, I wanted to check if this is a change that will be accepted.</p>
<p>Let me know if I should keep looking into this!</p> Ruby master - Misc #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 - Misc #15806 (Assigned): Explicitly initialise encodings on init to remove branches ...https://bugs.ruby-lang.org/issues/158062019-04-27T23:41:34Zmethodmissing (Lourens Naudé)lourens@bearmetal.eu
<p>References Github PR <a href="https://github.com/ruby/ruby/pull/2128" class="external">https://github.com/ruby/ruby/pull/2128</a></p>
<p>I noticed that the encoding table is loaded on startup of even just <code>miniruby</code> (minimal viable interpreter use case) through this backtrace during ruby setup:</p>
<pre><code>/home/lourens/src/ruby/ruby/miniruby(rb_enc_init+0x12) [0x56197b0c0c72] encoding.c:587
/home/lourens/src/ruby/ruby/miniruby(rb_usascii_encoding+0x1a) [0x56197b0c948a] encoding.c:1357
/home/lourens/src/ruby/ruby/miniruby(Init_sym+0x7a) [0x56197b24810a] symbol.c:42
/home/lourens/src/ruby/ruby/miniruby(rb_call_inits+0x1d) [0x56197b11afed] inits.c:25
/home/lourens/src/ruby/ruby/miniruby(ruby_setup+0xf6) [0x56197b0ec9d6] eval.c:74
/home/lourens/src/ruby/ruby/miniruby(ruby_init+0x9) [0x56197b0eca39] eval.c:91
/home/lourens/src/ruby/ruby/miniruby(main+0x5a) [0x56197b051a2a] ./main.c:41
</code></pre>
<p>Therefore I think it makes sense to instead initialize encodings explicitly just prior to symbol init, which is the first entry point into the interpreter loading that currently triggers <code>rb_enc_init</code> and remove the initialization check branches from the various lookup methods.</p>
<p>Some of the branches collapsed, <code>cachegrind</code> output, columns are <code>Ir Bc Bcm Bi Bim</code> with <code>Ir</code> (instructions retired), <code>Bc</code> (branches taken) and <code>Bcm</code> (branches missed) relevant here as there are no indirect branches (function pointers etc.):</p>
<p>(hot function, many instructions retired and branches taken and missed)</p>
<pre><code> . . . . . rb_encoding *
. . . . . rb_enc_from_index(int index)
835,669 0 0 0 0 {
13,133,536 6,337,652 50,267 0 0 if (!enc_table.list) {
3 0 0 0 0 rb_enc_init();
. . . . . }
23,499,349 8,006,202 293,161 0 0 if (index < 0 || enc_table.count <= (index &= ENC_INDEX_MASK)) {
. . . . . return 0;
. . . . . }
30,024,494 0 0 0 0 return enc_table.list[index].enc;
1,671,338 0 0 0 0 }
</code></pre>
<p>(cold function, representative of the utf8 variant more or less too)</p>
<pre><code> . . . . . rb_encoding *
. . . . . rb_ascii8bit_encoding(void)
. . . . . {
27,702 9,235 955 0 0 if (!enc_table.list) {
. . . . . rb_enc_init();
. . . . . }
9,238 0 0 0 0 return enc_table.list[ENCINDEX_ASCII].enc;
9,232 0 0 0 0 }
</code></pre>
<p>I think lazy loading encodings and populating the table is fine, but initializing it can be done more explicitly in the boot process.</p> Ruby master - Feature #15239 (Assigned): [patch] test-spec win32olehttps://bugs.ruby-lang.org/issues/152392018-10-20T19:32:07ZMSP-Greg (Greg L)
<p>Some of the current Win32OLE spec tests use the InternetExplorer control. This control is not available on Azure pipelines. Attached patch changes to use the MSXML control, adds a guard for it, and also does some refactoring to lower requires when not run under Windows, etc. Also, since the MSXML object is quite a bit 'smaller' than InternetExplorer, tests run faster.</p>
<p>Passed in my fork at <a href="https://ci.appveyor.com/project/MSP-Greg/ruby/builds/19663145" class="external">https://ci.appveyor.com/project/MSP-Greg/ruby/builds/19663145</a></p>
<p>Note also that since there have been recent commits stabilizing the spec suite, the above build job changed the mswin spec tests to run parallel, and they passed. The change from serial to parallel is not included in the patches. It is a separate commit in the branch on my fork.</p>
<p>GitHub patch is at:<br>
<a href="https://github.com/MSP-Greg/ruby/commit/d1daf9a66f491abfac5e84a50f152505baa1ccac.patch" class="external">https://github.com/MSP-Greg/ruby/commit/d1daf9a66f491abfac5e84a50f152505baa1ccac.patch</a></p> Ruby master - Feature #15166 (Assigned): 2.5 times faster implementation than current gcd implmen...https://bugs.ruby-lang.org/issues/151662018-09-26T18:30:29Zjzakiya (Jabari Zakiya)
<p>This is to be more explicit (and accurate) than <a href="https://bugs.ruby-lang.org/issues/15161" class="external">https://bugs.ruby-lang.org/issues/15161</a></p>
<p>This is my modified gcd benchmarks code, originally presented by Daniel Lemire (see 15161).</p>
<p><a href="https://gist.github.com/jzakiya/44eae4feeda8f6b048e19ff41a0c6566" class="external">https://gist.github.com/jzakiya/44eae4feeda8f6b048e19ff41a0c6566</a></p>
<p>Ruby's current implementation of Stein's gcd algorithm is only slightly faster than the<br>
code posted on the wikepedia page, and over 2.5 times slower than the fastest implementation<br>
in the benchmarks.</p>
<pre><code>[jzakiya@localhost ~]$ ./gcdbenchmarks
gcd between numbers in [1 and 2000]
gcdwikipedia7fast32 : time = 99
gcdwikipedia4fast : time = 121
gcdFranke : time = 126
gcdwikipedia3fast : time = 134
gcdwikipedia2fastswap : time = 136
gcdwikipedia5fast : time = 139
gcdwikipedia7fast : time = 138
gcdwikipedia2fast : time = 136
gcdwikipedia6fastxchg : time = 144
gcdwikipedia2fastxchg : time = 156
gcd_iterative_mod : time = 210
gcd_recursive : time = 215
basicgcd : time = 211
rubygcd : time = 267
gcdwikipedia2 : time = 321
gcd between numbers in [1000000001 and 1000002000]
gcdwikipedia7fast32 : time = 100
gcdwikipedia4fast : time = 121
gcdFranke : time = 126
gcdwikipedia3fast : time = 134
gcdwikipedia2fastswap : time = 136
gcdwikipedia5fast : time = 138
gcdwikipedia7fast : time = 138
gcdwikipedia2fast : time = 136
gcdwikipedia6fastxchg : time = 144
gcdwikipedia2fastxchg : time = 156
gcd_iterative_mod : time = 210
gcd_recursive : time = 215
basicgcd : time = 211
rubygcd : time = 269
gcdwikipedia2 : time = 323
</code></pre>
<p>This is Ruby's code per: <a href="https://github.com/ruby/ruby/blob/3abbaab1a7a97d18f481164c7dc48749b86d7f39/rational.c#L285-L307" class="external">https://github.com/ruby/ruby/blob/3abbaab1a7a97d18f481164c7dc48749b86d7f39/rational.c#L285-L307</a><br>
which is basically the wikepedia implementation.</p>
<pre><code>inline static long
i_gcd(long x, long y)
{
unsigned long u, v, t;
int shift;
if (x < 0)
x = -x;
if (y < 0)
y = -y;
if (x == 0)
return y;
if (y == 0)
return x;
u = (unsigned long)x;
v = (unsigned long)y;
for (shift = 0; ((u | v) & 1) == 0; ++shift) {
u >>= 1;
v >>= 1;
}
while ((u & 1) == 0)
u >>= 1;
do {
while ((v & 1) == 0)
v >>= 1;
if (u > v) {
t = v;
v = u;
u = t;
}
v = v - u;
} while (v != 0);
return (long)(u << shift);
}
</code></pre>
<p>This is the fastest implementation from the benchmarks. (I originally, wrongly, cited<br>
the implementation in the article, which is 4|5th fastest in benchmarks, but<br>
still almost 2x faster than the Ruby implementation.)</p>
<pre><code>// based on wikipedia's article,
// fixed by D. Lemire, K. Willets
unsigned int gcdwikipedia7fast32(unsigned int u, unsigned int v)
{
int shift, uz, vz;
if ( u == 0) return v;
if ( v == 0) return u;
uz = __builtin_ctz(u);
vz = __builtin_ctz(v);
shift = uz > vz ? vz : uz;
u >>= uz;
do {
v >>= vz;
int diff = v;
diff -= u;
if ( diff == 0 ) break;
vz = __builtin_ctz(diff);
if ( v < u ) u = v;
v = abs(diff);
} while( 1 );
return u << shift;
}
</code></pre>
<p>The key to speeding up all the algorithms is using the <code>__builtin_ctz(x)</code> directive<br>
to determine the number of trailing binary '0's.</p> Ruby master - Feature #14901 (Assigned): [PATCH] do not block SIGCHLD in normal Ruby Threadshttps://bugs.ruby-lang.org/issues/149012018-07-08T02:53:23Znormalperson (Eric Wong)normalperson@yhbt.net
<p><a class="user active user-mention" href="https://bugs.ruby-lang.org/users/10073">@k0kubun (Takashi Kokubun)</a>: any opinions on this? Thanks.</p>
<pre><code>I blocked SIGCHLD in normal Ruby Threads for [Bug #14867]
because I noticed at least two places which could not deal
with spurious wakeups in our test suite.
I also want to get rid of timer-thread due to resource
limitations <a href="https://blade.ruby-lang.org/ruby-core/87773">[ruby-core:87773]</a>. MJIT causes many SIGCHLD signals
so I found the following problems with cppflags=-DMJIT_FORCE_ENABLE=1
* OpenSSL::PKey::*.new does not resume on handle signals.
rhenium acknowledged the problem and it should be in trunk soon:
https://bugs.ruby-lang.org/issues/14882
* test/-ext-/gvl/test_last_thread.rb does not handle spurious
wakeups. Original report is in Japanese:
https://bugs.ruby-lang.org/issues/11237
I don't think it's a realistic expectation for code to be
unable to deal with spurious wakeups.
One alternative could be to handle signals with MJIT thread
when MJIT is enabled, or to lazy-spawn timer thread to handle
signals when MJIT is enabled (MJIT + gcc requires a lot of
resources, anyways).
</code></pre> Ruby master - Feature #14476 (Assigned): Adding same_all? for checking whether all items in an Ar...https://bugs.ruby-lang.org/issues/144762018-02-14T15:41:30Zmrkn (Kenta Murata)muraken@gmail.com
<p>In this issue, I propose to introduce <code>same_all?</code> instance method of <code>Array</code> class. This new method checks whether all items in the receiver are the same.</p>
<p>Today, I needed to write a code to judge whether all items in an <code>Array</code> are the same. I wanted to make the following expression, which I've written first, more efficient.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">ary</span><span class="p">.</span><span class="nf">all?</span> <span class="p">{</span><span class="o">|</span><span class="n">e</span><span class="o">|</span> <span class="n">e</span><span class="p">.</span><span class="nf">foo</span> <span class="o">==</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">foo</span> <span class="p">}</span>
</code></pre>
<p>I considered about the following simpler case, too.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">ary</span><span class="p">.</span><span class="nf">all?</span> <span class="p">{</span><span class="o">|</span><span class="n">e</span><span class="o">|</span> <span class="n">e</span> <span class="o">==</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="p">}</span>
</code></pre>
<p>As I discussed with some CRuby committers and my colleagues at Speee, Inc., I found that both cases can be written more efficiently as follows:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># for the 1st case</span>
<span class="n">ary</span><span class="p">.</span><span class="nf">empty?</span> <span class="o">||</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">foo</span><span class="p">.</span><span class="nf">yield_self</span> <span class="p">{</span><span class="o">|</span><span class="n">e0</span><span class="o">|</span> <span class="n">ary</span><span class="p">[</span><span class="mi">1</span><span class="o">..-</span><span class="mi">1</span><span class="p">].</span><span class="nf">all?</span> <span class="p">{</span><span class="o">|</span><span class="n">e</span><span class="o">|</span> <span class="n">e</span><span class="p">.</span><span class="nf">foo</span> <span class="o">==</span> <span class="n">e0</span> <span class="p">}</span> <span class="p">}</span><span class="err"> </span>
<span class="c1"># for the 2nd case</span>
<span class="n">ary</span><span class="p">.</span><span class="nf">empty?</span> <span class="o">||</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="o">..-</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="n">ary</span><span class="p">[</span><span class="mi">1</span><span class="o">..-</span><span class="mi">1</span><span class="p">]</span>
</code></pre>
<p>However, it is not easy to understand the intent of either expression, which is to check whether all items are the same.</p>
<p>I want to give this feature a clear name to make code readable. And I think it should be provided as a core feature because it can be made more efficient by being implemented in C language.</p>
<p>The benchmark script is: <a href="https://gist.github.com/mrkn/26a0fcfc431a45fe809fbbef95aceaf5" class="external">https://gist.github.com/mrkn/26a0fcfc431a45fe809fbbef95aceaf5</a><br>
I used it to find the efficient expressions. The example result of this benchmark on my MacBook Pro is here.</p>
<pre><code>$ ruby -v bench.rb
ruby 2.6.0dev (2018-02-14 trunk 62402) [x86_64-darwin16]
----------------------------------------
Benchmark case: shuffle
user system total real
all?-method-1 0.001525 0.000088 0.001613 ( 0.001632)
all?-method-2 0.000489 0.000031 0.000520 ( 0.000565)
all?-method-3 0.000444 0.000039 0.000483 ( 0.000482)
all?-item 0.000325 0.000078 0.000403 ( 0.000402)
opt-method 0.655959 0.033814 0.689773 ( 0.708515)
opt-item 0.000316 0.000001 0.000317 ( 0.000317)
----------------------------------------
Benchmark case: tail0
user system total real
all?-method-1 9.412810 0.231126 9.643936 ( 9.681118)
all?-method-2 5.375075 0.137908 5.512983 ( 5.754550)
all?-method-3 5.226132 0.167640 5.393772 ( 5.507031)
all?-item 0.873700 0.007545 0.881245 ( 0.917210)
opt-method 5.319648 0.172547 5.492195 ( 5.633140)
opt-item 0.174349 0.001974 0.176323 ( 0.183002)
----------------------------------------
Benchmark case: head0
user system total real
all?-method-1 0.002421 0.000068 0.002489 ( 0.002489)
all?-method-2 0.002169 0.000213 0.002382 ( 0.002382)
all?-method-3 0.001624 0.000026 0.001650 ( 0.001651)
all?-item 0.000623 0.000001 0.000624 ( 0.000624)
opt-method 4.779120 0.146312 4.925432 ( 4.951167)
opt-item 0.000629 0.000001 0.000630 ( 0.000629)
----------------------------------------
Benchmark case: all1
user system total real
all?-method-1 9.379650 0.255865 9.635515 ( 9.683078)
all?-method-2 4.950280 0.150659 5.100939 ( 5.140174)
all?-method-3 4.857898 0.129125 4.987023 ( 5.003142)
all?-item 0.694113 0.001295 0.695408 ( 0.702370)
opt-method 5.032373 0.121708 5.154081 ( 5.189599)
opt-item 0.170540 0.002069 0.172609 ( 0.180343)
</code></pre> Ruby master - Feature #14412 (Assigned): DRb UNIX on local machine: add support for getpeereid()https://bugs.ruby-lang.org/issues/144122018-01-27T17:26:32ZAnonymous
<p>Hi,</p>
<p><code>UNIXSocket</code> has this method <code>#getpeereid()</code> which returns effective user ID and effective group ID.</p>
<p>DRb using <code>drbunix://</code> on local machine doesn't support that method. In my use case, I need to verify clients via that method. So it would be great if you add support to DRb.</p>
<p>Actually that method <code>#getpeereid()</code> is from <code>BaseSocket</code>, but documentation states that it only supports UNIX sockets. I mean, it's a general method from parent class. So you can do the same with DRb: add some similar method, but only works via <code>drbunix://</code> on local machine. Otherwise you can raise error...</p>
<p>Thank you,</p> Ruby master - Misc #13622 (Assigned): Documentation missinghttps://bugs.ruby-lang.org/issues/136222017-06-02T14:08:27Zsergzhum (Sergey Zhumatiy)
<p>In documentation for method IO.nread important information is missing: you must do 'require "io/wait"' before using it. May be some other methods of IO in 'io/wait' are missed this IMPORTANT notice.</p> Ruby master - Feature #13577 (Assigned): Digest.file accidentally receives File object but uses f...https://bugs.ruby-lang.org/issues/135772017-05-19T09:03:19Znaruse (Yui NARUSE)naruse@airemix.jp
<p>Digest::SHA256.file()'s first argument is file path name but it accidentally accepts file object.<br>
But for file objects created with O_TMPFILE to_path returns the directory of the temporary file and this File.open will fail.</p>
<pre><code> class ::Digest::Class
# Creates a digest object and reads a given file, _name_.
# Optional arguments are passed to the constructor of the digest
# class.
#
# p Digest::SHA256.file("X11R6.8.2-src.tar.bz2").hexdigest
# # => "f02e3c85572dc9ad7cb77c2a638e3be24cc1b5bea9fdbb0b0299c9668475c534"
def self.file(name, *args)
new(*args).file(name)
end
end
module Instance
# Updates the digest with the contents of a given file _name_ and
# returns self.
def file(name)
File.open(name, "rb") {|f|
buf = ""
while f.read(16384, buf)
update buf
end
}
self
end
</code></pre> Ruby master - Feature #13516 (Assigned): Improve the text of the circular require warninghttps://bugs.ruby-lang.org/issues/135162017-04-27T22:41:20Zjaredbeck (Jared Beck)jared@jaredbeck.com
<p>The warning currently reads:</p>
<p><code>loading in progress, circular require considered harmful - /my/file.rb</code></p>
<p>I think it would be more helpful like:</p>
<p><code>Circular require: Loading of /my/file.rb is already in progress, but require was called again</code></p>
<p>I think this is more helpful because it clarifies that /my/file.rb is the problem.</p>
<p>What do you think? Thanks!</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 #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 - Bug #12582 (Assigned): OpenSSL Authenticated Encryption should check for tag lengthhttps://bugs.ruby-lang.org/issues/125822016-07-11T07:35:30Zpatrick.oscity (Patrick Oscity)
<p>The current API for using ciphers with Authenticated Encryption (currently only AES-GCM) is rather misleading and quickly leads to subtle bugs related to the length of <code>auth_tag</code>.</p>
<p>In particular, the current implementation will <em>not</em> check for the length of the <code>auth_tag</code>. Because GCM mode allows arbitrary sizes of the <code>auth_tag</code> up to 128 bytes, only a single byte needs to be supplied to make the authentication pass. This means that an attacker needs at most 256 attempts in order to forge a valid <code>auth_tag</code>.</p>
<pre><code>data = 'secret'
cipher = OpenSSL::Cipher.new('aes-128-gcm')
cipher.encrypt
key = cipher.random_key
iv = cipher.random_iv
cipher.auth_data = 'auth_data'
ciphertext = cipher.update(data) + cipher.final
auth_tag = cipher.auth_tag
auth_tag = auth_tag[0] # single byte is sufficient
cipher = OpenSSL::Cipher.new('aes-128-gcm')
cipher.decrypt
cipher.key = key
cipher.iv = iv
cipher.auth_tag = auth_tag
cipher.auth_data = 'auth_data'
data = cipher.update(ciphertext) + cipher.final
# NO error raised
</code></pre>
<p>Currently, the only way to prevent such attacks is to manually assert the correct <code>auth_tag</code> length when decrypting/authenticating.</p>
<pre><code>raise 'incorrect auth_tag length' unless auth_tag.length == 16
</code></pre>
<p>I suggest the following improvements:</p>
<a name="Documentation-should-mention-the-importance-of-manually-checking-auth_tag-length"></a>
<h3 >Documentation should mention the importance of manually checking <code>auth_tag</code> length<a href="#Documentation-should-mention-the-importance-of-manually-checking-auth_tag-length" class="wiki-anchor">¶</a></h3>
<p>This can/should be done immediately even if the API should not change.</p>
<a name="Authentication-tag-length-should-be-an-input-parameter-to-the-cipher"></a>
<h3 >Authentication tag length should be an input parameter to the cipher<a href="#Authentication-tag-length-should-be-an-input-parameter-to-the-cipher" class="wiki-anchor">¶</a></h3>
<p>To improve the usability of the API and unburden users from performing additional manual checks without compromising security, I suggest to add an <code>auth_tag_len</code> accessor. This can be used to determine the size of the <code>auth_tag</code> both when generating and when authenticating the <code>auth_tag</code>. The default value should be 16 bytes (see below).</p>
<h3>
<code>#auth_tag</code> should use <code>auth_tag_len</code> to determine the output length</h3>
<p>During encryption:</p>
<p>If no parameter is given, <code>#auth_tag</code> should return an authentication tag according to the length configured in <code>auth_tag_len</code>.</p>
<p>If a length parameter is given, <code>#auth_tag</code> should use the supplied parameter to determine the length of the authentication tag. Although this parameter is not as useful any more it should be kept for backwards compatibility. Maybe it should be deprecated.</p>
<p>Currently the API supports different tag lengths by passing the length parameter to <code>#auth_tag</code>. This currently defaults to 16 bytes, which should be the default value for <code>auth_tag_len</code> in order to keep backwards compatibility.</p>
<h3>
<code>#final</code> should use <code>auth_tag_len</code> to assert the correct length of the <code>auth_tag</code>
</h3>
<p>During decryption:</p>
<p><code>auth_tag_len</code> should be used to assert that the supplied <code>auth_tag</code> has the correct length. The big difference to the existing API lies here, because users need to actively change the value of <code>auth_tag_len</code> in order to allow shorter tags.</p>
<p>When the check fails, an <code>OpenSSL::Cipher::CipherError</code> should be raised. The same type of error is already raised when authentication fails, so existing users should be fine without having to touch their error handling. A descriptive error message should be helpful. In order to distinguish between such errors and "actual" verification errors, we could also add a descriptive message for the latter.</p>
<p>I'd be happy to implement these changes, but I wanted to discuss them first.</p> Ruby master - Feature #12281 (Assigned): Allow lexically scoped use of refinements with `using {}...https://bugs.ruby-lang.org/issues/122812016-04-14T03:48:01Zdanielpclark (Daniel P. Clark)6ftdan@gmail.com
<p>In Ruby 2.2.3 a refinement could be used in a begin/end block.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Moo</span>
<span class="n">refine</span> <span class="no">Fixnum</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">to_s</span>
<span class="s2">"moo"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">begin</span> <span class="c1"># valid Ruby 2.2.3 and NOT Ruby 2.3</span>
<span class="n">using</span> <span class="no">Moo</span>
<span class="mi">1</span><span class="p">.</span><span class="nf">to_s</span>
<span class="k">end</span>
<span class="c1"># => "moo"</span>
</code></pre>
<p>Since this use case has been removed I would like to propose an alternative.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">using</span> <span class="no">Moo</span> <span class="k">do</span>
<span class="mi">1</span><span class="p">.</span><span class="nf">to_s</span>
<span class="k">end</span>
<span class="c1"># => "moo"</span>
</code></pre>
<p>I would like to propose allowing refinements to take a block and perform the refinement within the block and work just as if it were in it's own lexically scoped class.</p>
<p>I've been writing a lot of Rust lately and have found that their way of implementing Traits is just like Ruby's refinements except for that you can use Rust's version of refinements anywhere. Since Ruby's implementation is strictly lexically scoped I merely suggest a block syntax for <code>using</code> to allow greater expansion of refinements.</p>
<pre><code class="rust syntaxhl" data-language="rust"><span class="c1">// Rust</span>
<span class="k">impl</span> <span class="n">MyCapitalize</span> <span class="k">for</span> <span class="nb">String</span> <span class="p">{</span>
<span class="k">fn</span> <span class="nf">my_capitalize</span><span class="p">(</span><span class="o">&</span><span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="k">Self</span> <span class="p">{</span>
<span class="c1">// code here</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">use</span> <span class="n">MyCapitalize</span><span class="p">;</span>
<span class="nn">String</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="s">"hello"</span><span class="p">)</span><span class="nf">.my_capitalize</span><span class="p">()</span>
</code></pre>
<p>Rust lets you use the "refinement" of the trait implementation anywhere you use <code>use</code> just like Ruby's <code>using</code>. But currently Ruby restricts where <code>using</code> can be used. I would like that restriction to be lifted by allowing <code>using</code> to take a block.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># Ruby</span>
<span class="k">module</span> <span class="nn">MyCapitalize</span>
<span class="n">refine</span> <span class="no">String</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">my_capitalize</span>
<span class="c1"># code here</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">using</span> <span class="no">MyCapitalize</span> <span class="k">do</span>
<span class="s2">"hello"</span><span class="p">.</span><span class="nf">my_capitalize</span>
<span class="k">end</span>
<span class="c1"># => "Hello"</span>
</code></pre>
<p>This way we keep Ruby's strict lexical scope behavior and at the same time allow refinement usage anywhere we need it.</p> Ruby master - Feature #11955 (Assigned): Expose Object that Receives logs in Loggerhttps://bugs.ruby-lang.org/issues/119552016-01-05T21:59:29Zschneems (Richard Schneeman)
<p>I need to be able to perform logic based on the destination of a current logger, this is currently not possible without <code>instance_variable_get</code>. Why would you need to see what destination a logger is going to? There is a common pattern in long lived programs like webservers. You want logs on disk for later reference, but you also want them in STDOUT to make development and debugging easier. Rails does this in development mode. Since there is no way to see if a logger is already going to STDOUT, it gets extended to log to STDOUT so logs show up twice.</p>
<p>While that example was complicated the logic I want is very simple: if you have a logger that is logging to STDOUT, do nothing, otherwise log to STDOUT and current logger. You cannot do this today without exposing the destination of the logger. This patch exposes the logger destination and allows us to write code like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">make_sure_logging_to_stdout</span><span class="p">(</span><span class="n">logger</span><span class="p">)</span>
<span class="k">unless</span> <span class="n">logger</span><span class="p">.</span><span class="nf">destination</span> <span class="o">==</span> <span class="no">STDOUT</span> <span class="c1"># <==== Cannot do this today</span>
<span class="n">stdout_logger</span> <span class="o">=</span> <span class="o">::</span><span class="no">Logger</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">STDOUT</span><span class="p">)</span>
<span class="n">logger</span><span class="p">.</span><span class="nf">extend</span><span class="p">(</span><span class="no">Module</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">add</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">stdout_logger</span><span class="p">.</span><span class="nf">add</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">super</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="k">end</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">logger</span> <span class="o">=</span> <span class="no">Logger</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">STDOUT</span><span class="p">)</span>
<span class="n">make_sure_logging_to_stdout</span><span class="p">(</span><span class="n">logger</span><span class="p">)</span>
<span class="n">logger</span><span class="p">.</span><span class="nf">fatal</span><span class="p">(</span><span class="s2">"An error has occured"</span><span class="p">)</span>
</code></pre>
<p>We should be able to inspect the destination of a logger, this patch enables this functionality.</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 #10782 (Assigned): Patch: Add constants for BigDecimal for ZERO, ONE, TENhttps://bugs.ruby-lang.org/issues/107822015-01-25T16:24:59Zgarysweaver (Gary Weaver)garysweaver@gmail.com
<p>We found with use of BigDecimal that we were often needing to compare BigDecimal with zero or initialize BigDecimal as 0 for a default value. This introduces a bit move overhead than is typically needed, since a simple BigDecimal.new('0') will suffice without any additional arguments. This BigDecimal instance does not change, so it makes sense to make it a constant.</p>
<p>In Java, they found that constants for zero, one, and ten were useful (see <a href="http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#ZERO" class="external">http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#ZERO</a>), so I thought it would be good to submit a patch for Ruby 2.3.0, just to see whether others would find this useful. I understand that we don't want to have constants for every possible value, and that it might be helpful if these had the same object id across ruby implementations similar to lower integer values having the same object id, however I don't think it is necessary or useful to compare object_id's for BigDecimal value comparison- the point is only not to have to retain and create new instances of BigDecimal for ZERO, ONE, or TEN.</p> Ruby master - Misc #10560 (Assigned): confusion between x=x+y, x+=y, x.concat(y) and y.each{|z| x...https://bugs.ruby-lang.org/issues/105602014-12-01T15:53:01Zmpapis (Michal Papis)mpapis@gmail.com
<p>while discussing a ticket I have noticed that there is no documentation for <code>+=</code></p>
<p>I was expecting <code>+=</code> to behave as <code>concat</code> but instead it behaves as <code>x=x+y</code> which for every operation clones the array and updates the variable with new value so it behaves similarly to <code>x=x.dup.concat(y)</code> and is slightly faster, but using plane <code>x.concat(y)</code> is a lot faster from both <code>each<<</code> and <code>+=</code></p>
<p>I would either like to get:</p>
<ul>
<li>updated docs that describe concept of <code>+=</code> and show the difference from <code>concat</code>
</li>
<li>or change <code>+=</code> to use <code>concat</code> which is faster - and add docs ;) (I would expect <code>+=</code> to use <code>concat</code> when available)</li>
</ul>
<p>here is a test:</p>
<pre><code>require 'benchmark'
rep = 10_000
Benchmark.bmbm do |x|
{
1..25 => [],
"a".."z" => "",
}.each do |base, storage|
base = base.to_a
basej = base
class_name = storage.class.to_s
x.report(class_name+'#concat') do
a = storage.dup
basej = base.join if storage == ""
rep.times { a.concat(basej) }
end
x.report(class_name+'#<<') do
a = storage.dup
basej = base.join if storage == ""
rep.times { base.each { |e| a << e } }
end
x.report(class_name+'#+=') do
a = storage.dup
basej = base.join if storage == ""
rep.times { a += basej }
end
x.report(class_name+'#dup.concat') do
a = storage.dup
basej = base.join if storage == ""
rep.times { a = a.dup.concat(basej) }
end
end
end
</code></pre>
<p>and here are results on my machine:</p>
<pre><code> user system total real
Array#concat 0.000000 0.000000 0.000000 ( 0.001422)
Array#<< 0.020000 0.000000 0.020000 ( 0.014356)
Array#+= 1.270000 0.230000 1.500000 ( 1.498558)
Array#dup.concat 2.720000 0.190000 2.910000 ( 2.915701)
String#concat 0.000000 0.000000 0.000000 ( 0.001072)
String#<< 0.030000 0.000000 0.030000 ( 0.025828)
String#+= 0.130000 0.010000 0.140000 ( 0.135143)
String#dup.concat 0.210000 0.020000 0.230000 ( 0.227470)
</code></pre> Ruby master - Feature #10481 (Assigned): Add "if" and "unless" clauses to rescue statementshttps://bugs.ruby-lang.org/issues/104812014-11-05T19:20:10Zjavawizard (Alex Boyd)alex@opengroove.org
<p>I'd like to propose a syntax change: allow boolean "if" and "unless" clauses to follow a rescue statement.</p>
<p>Consider the following:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">begin</span>
<span class="o">...</span>
<span class="k">rescue</span> <span class="no">SomeError</span> <span class="o">=></span> <span class="n">e</span>
<span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="nf">error_code</span> <span class="o">==</span> <span class="mi">1</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span><span class="o">...</span>
<span class="k">else</span>
<span class="k">raise</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>This is a fairly common way of dealing with exceptions where some condition above and beyond the exception's type determines whether the exception should be rescued. It's verbose, though, and it's not obvious at first glance exactly what conditions are being rescued, especially if "...handle error..." is more than a few lines long. I propose that the following be allowed:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">begin</span>
<span class="o">...</span>
<span class="k">rescue</span> <span class="no">SomeError</span> <span class="o">=></span> <span class="n">e</span> <span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="nf">error_code</span> <span class="o">==</span> <span class="mi">1</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span><span class="o">...</span>
<span class="k">end</span>
</code></pre>
<p>"unless" would, of course, be allowed as well:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">begin</span>
<span class="o">...</span>
<span class="k">rescue</span> <span class="no">SomeError</span> <span class="o">=></span> <span class="n">e</span> <span class="k">unless</span> <span class="n">e</span><span class="p">.</span><span class="nf">error_code</span> <span class="o">==</span> <span class="mi">2</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span><span class="o">...</span>
<span class="k">end</span>
</code></pre>
<p>A rescue statement whose boolean condition failed would be treated the same as if the exception being raised didn't match the exception being rescued, and move on to the next rescue statement:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">begin</span>
<span class="o">...</span>
<span class="k">rescue</span> <span class="no">SomeError</span> <span class="o">=></span> <span class="n">e</span> <span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="nf">error_code</span> <span class="o">==</span> <span class="mi">1</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span> <span class="n">code</span> <span class="mi">1</span><span class="o">...</span>
<span class="k">rescue</span> <span class="no">SomeError</span> <span class="o">=></span> <span class="n">e</span> <span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="nf">error_code</span> <span class="o">==</span> <span class="mi">2</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span> <span class="n">code</span> <span class="mi">2</span><span class="o">...</span>
<span class="k">end</span>
</code></pre>
<p>And finally, catch-all rescue statements would be allowed as well:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">begin</span>
<span class="o">...</span>
<span class="k">rescue</span> <span class="o">=></span> <span class="n">e</span> <span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="nf">message</span> <span class="o">==</span> <span class="s2">"some error"</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span><span class="o">...</span>
<span class="k">end</span>
</code></pre> Ruby master - Feature #10038 (Assigned): Extend ObjectSpace.dump to expose buffer addresses for S...https://bugs.ruby-lang.org/issues/100382014-07-15T07:15:45Zko1 (Koichi Sasada)
<p>ObjectSpace.dump() expose internal information in JSON.<br>
How about to expose buffer addresses for String and Array?</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">Index: ext/objspace/objspace_dump.c
===================================================================
</span><span class="gd">--- ext/objspace/objspace_dump.c (revision 46821)
</span><span class="gi">+++ ext/objspace/objspace_dump.c (working copy)
</span><span class="p">@@ -178,12 +178,16 @@</span> dump_object(VALUE obj, struct dump_confi
dump_append(dc, ", \"broken\":true");
if (FL_TEST(obj, RSTRING_FSTR))
dump_append(dc, ", \"fstring\":true");
<span class="gd">- if (STR_SHARED_P(obj))
</span><span class="gi">+
+ if (STR_SHARED_P(obj)) {
</span> dump_append(dc, ", \"shared\":true");
<span class="gi">+ }
</span> else {
dump_append(dc, ", \"bytesize\":%ld", RSTRING_LEN(obj));
<span class="gd">- if (!STR_EMBED_P(obj) && !STR_SHARED_P(obj) && (long)rb_str_capacity(obj) != RSTRING_LEN(obj))
</span><span class="gi">+ if (!STR_EMBED_P(obj) && !STR_SHARED_P(obj) && (long)rb_str_capacity(obj) != RSTRING_LEN(obj)) {
</span> dump_append(dc, ", \"capacity\":%ld", rb_str_capacity(obj));
<span class="gi">+ dump_append(dc, ", \"ptr\":\"%p\"", RSTRING_PTR(obj));
+ }
</span>
if (is_ascii_string(obj)) {
dump_append(dc, ", \"value\":");
<span class="p">@@ -205,8 +209,14 @@</span> dump_object(VALUE obj, struct dump_confi
dump_append(dc, ", \"length\":%ld", RARRAY_LEN(obj));
if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, ELTS_SHARED))
dump_append(dc, ", \"shared\":true");
<span class="gd">- if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, RARRAY_EMBED_FLAG))
</span><span class="gi">+ if (RARRAY_LEN(obj) > 0) {
+ if (FL_TEST(obj, RARRAY_EMBED_FLAG)) {
</span> dump_append(dc, ", \"embedded\":true");
<span class="gi">+ }
+ else {
+ dump_append(dc, ", \"ptr\":\"%p\"", RARRAY_PTR(obj));
+ }
+ }
</span> break;
case T_CLASS:
</code></pre>
<p>With this hack, we can know the real memory address of them and cooperate with other native tools.</p>
<p>BTW, ObjectSpace.dump() should support T_SYMBOL.</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 #9768 (Assigned): Method that is visible only within a certain module/classhttps://bugs.ruby-lang.org/issues/97682014-04-22T09:57:35Zsawa (Tsuyoshi Sawada)
<p>Some frameworks/libraries monkeypatch their own methods on Ruby core classes like <code>String</code>, <code>Hash</code>, <code>Array</code>, etc., and that is often causing problems/concerns of name conflict.</p>
<p>Seeing that these custom methods are used only in the context of a certain module/class, I request for a way to define a method (<code>foo</code>) on a module/class (<code>A</code>) so that it will be visible only from within a specified module/class (<code>B</code>) or its descendants. The following illustrates this situation:</p>
<pre><code>A.new.foo # => undefined
class B
A.new.foo # => defined
def bar
A.new.foo # => defined
end
def self.baz
A.new.foo # => defined
end
end
class C < B
A.new.foo # => defined
def bar
A.new.foo # => defined
end
def self.baz
A.new.foo # => defined
end
end
</code></pre>
<p>I do not have a certain syntax for this in mind, but I think it can be made much simpler, compared to the complicated syntax of refinement.</p>
<p>This is reminiscent of refinement, but they are pretty much different.</p>
<p>Refinement's purpose is to let certain methods be accessible from only a certain file. A typical use case would be a library developer defining their methods to be used from within the library and making such methods inaccessible from the end user.</p>
<p>On the other hand, the idea I am proposing here is for making method accessible from any file, but only within a certain module/class. A typical use case would be defining a method to be used by an end user, but only from within a context of certain module/class.</p> Ruby master - Feature #9235 (Assigned): Documentation for commercial supporthttps://bugs.ruby-lang.org/issues/92352013-12-10T05:36:24Zzzak (zzak _)
<p>We should document the following:</p>
<ul>
<li>What happens when a Ruby version goes EOL?</li>
<li>What can (my) company do to help maintain an EOL ruby?</li>
<li>How do we backport security patches?</li>
<li>How do we run tests?</li>
<li>How do we release our own version of ruby?</li>
</ul> Ruby master - Bug #9189 (Assigned): Build failure on Windows in case of nonascii TEMP environment.https://bugs.ruby-lang.org/issues/91892013-12-01T18:06:20Zphasis68 (Heesob Park)phasis@gmail.com
<p>I experienced a build failure during build extension library with trunk on Windows.</p>
<pre><code>make[2]: Entering directory `/c/work/ruby-2.1.0-r43936/ext/bigdecimal'
generating bigdecimal-i386-mingw32.def
compiling bigdecimal.c
In file included from bigdecimal.c:20:0:
bigdecimal.h:62:1: error: static declaration of 'labs' follows non-static declar
ation
make[2]: *** [bigdecimal.o] Error 1
make[2]: Leaving directory `/c/work/ruby-2.1.0-r43936/ext/bigdecimal'
make[1]: *** [ext/bigdecimal/all] Error 2
make[1]: Leaving directory `/c/work/ruby-2.1.0-r43936'
make: *** [build-ext] Error 2
</code></pre>
<p>I found the cause of this error is mkmk failure.<br>
Here is a part of mkmf.log</p>
<pre><code>have_func: checking for labs() in stdlib.h... -------------------- no
"i686-w64-mingw32-gcc -o conftest.exe -I../../.ext/include/i386-mingw32 -I../.././include -I../.././ext/bigdecimal -D_WIN32_WINNT=0x0501 -D_FILE_OFFSET_BITS=64 -O3 -fno-omit-frame-pointer -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration conftest.c -L. -L../.. -L. -lmsvcrt-ruby210-static -lshell32 -lws2_32 -liphlpapi -limagehlp -lshlwapi "
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Cannot create temporary file in C:\Users\??苑?AppData\Local\Temp\: Invalid argument
</code></pre>
<p>The TEMP environment varable is</p>
<pre><code>C:\work\ruby-2.1.0-r43936>set TEMP
TEMP=C:\Users\희섭\AppData\Local\Temp
</code></pre>
<p>It seems that miniruby cannot handle encoding properly.</p>
<pre><code>C:\work\ruby-2.1.0-r43936>miniruby -ve "p ENV['TEMP']"
ruby 2.1.0dev (2013-11-30 trunk 43936) [i386-mingw32]
"C:\\Users\\\xED\x9D\xAC\xEC\x84\xAD\\AppData\\Local\\Temp"
C:\work\ruby-2.1.0-r43936>miniruby.exe -ve "p ENV['TEMP'].encoding"
ruby 2.1.0dev (2013-11-30 trunk 43936) [i386-mingw32]
#<Encoding:ASCII-8BIT>
</code></pre>
<p>Whereas, the final ruby can handle encoding properly.</p>
<pre><code>C:\work>ruby -ve "p ENV['TEMP']"
ruby 2.1.0dev (2013-11-30 trunk 43923) [i386-mingw32]
"C:\\Users\\희섭\\AppData\\Local\\Temp"
C:\work>ruby -ve "p ENV['TEMP'].encoding"
ruby 2.1.0dev (2013-11-30 trunk 43923) [i386-mingw32]
#<Encoding:CP949>
</code></pre> Ruby master - Misc #9136 (Assigned): Deprecated Enumerator.new(object, method) bad for BasicObjecthttps://bugs.ruby-lang.org/issues/91362013-11-21T22:18:28Zatlas (Atlas Prime)a7145@live.com
<p>=begin<br>
Documentation it says:</p>
<p>In the second, deprecated, form, a generated Enumerator iterates over the given object using the given method with the given arguments passed.</p>
<p>Use of this form is discouraged. Use Kernel#enum_for or Kernel#to_enum instead.</p>
<pre><code> e = Enumerator.new(ObjectSpace, :each_object)
#-> ObjectSpace.enum_for(:each_object)
</code></pre>
<p>But (({#enum_for})) and (({#to_enum})) are not available to subclasses of (({BasicObject})). In fact, I was defining (({#to_enum})) for a class that is a subclass of (({BasicObject})), and now I get warning of deprecation.<br>
=end</p> Ruby master - Bug #9115 (Assigned): Logger traps all exceptions; breaks Timeouthttps://bugs.ruby-lang.org/issues/91152013-11-16T12:30:25Zcphoenix (Chris Phoenix)cphoenix@gmail.com
<p>Line 577-579 of logger.rb</p>
<pre><code> rescue Exception => ignored
warn("log writing failed. #{ignored}")
end
</code></pre>
<p>Thus, when the system times out in the middle of writing a log message, it warns "log writing failed. execution expired" and just keeps right on running.</p>
<p>This is true in 1.9.3 as well. I haven't looked at older versions.</p>
<p>Pardon me while I go grep "rescue Exception" in the entire Ruby codebase, and see whether I can reliably use Timeout at all...</p>
<p>OK, you might check out C:\Ruby200\lib\ruby\gems\2.0.0\gems\activerecord-3.2.13\lib\active_record\railties\databases.rake</p>
<p>All the other "rescue Exception" seem to re-raise it, except maybe C:\Ruby200\lib\ruby\2.0.0\xmlrpc\server.rb and C:\Ruby200\lib\ruby\gems\2.0.0\gems\activesupport-3.2.13\lib\active_support\callbacks.rb</p> Ruby master - Feature #9020 (Assigned): Net::HTTPResponse predicate/query methodshttps://bugs.ruby-lang.org/issues/90202013-10-14T20:43:15Ztimcraft (Tim Craft)
<a name="SUMMARY"></a>
<h1 >SUMMARY<a href="#SUMMARY" class="wiki-anchor">¶</a></h1>
<p>I would like to propose adding predicate/query methods to Net::HTTPResponse for testing the status/type of response. For example:</p>
<pre><code>response.ok?
response.not_found?
response.client_error?
response.server_error?
</code></pre>
<a name="BACKGROUND"></a>
<h1 >BACKGROUND<a href="#BACKGROUND" class="wiki-anchor">¶</a></h1>
<p>The approach I've most commonly used/encountered for testing the status of a response is to compare with an integer, for example:</p>
<pre><code>response.code.to_i == 200
</code></pre>
<p>Subjectively I could say this kind of code is awkward/tedious to type, and not very "intention revealing". More practically/objectively it's a potential source of error. By mistyping the "magic number" it's possible for this expression to "silently fail" and test the wrong status. That would be an easy thing to spot in these examples, but much more difficult to track down within a typical codebase.</p>
<p>Another approach would be to test the type/class of the response object, for example:</p>
<pre><code>Net::HTTPOK === response
</code></pre>
<p>Subjectively I would say this doesn't feel very Ruby-ish. More practically/objectively it tightly couples the caller to the implementation details of Net::HTTP, making it difficult to stub or swap in a different library.</p>
<a name="PROPOSAL"></a>
<h1 >PROPOSAL<a href="#PROPOSAL" class="wiki-anchor">¶</a></h1>
<p>I would like to propose adding predicate/query methods to Net::HTTPResponse in order to encapsulate the implementation details of testing for different statuses and to provide a more abstract interface to the caller. For example:</p>
<pre><code>response.ok?
response.not_found?
</code></pre>
<p>This is more concise/readable. In most cases it would be easier and "less fiddly" to type out than the existing approaches presented above.</p>
<p>Compared to testing with integers it is one method call instead of three (I'm considering that as better from a readability perspective, not a performance perspective), and it eliminates the "failing silently" issue.</p>
<p>Compared to testing the type/class of the response object it doesn't couple the caller to implementation details of Net::HTTP, so it would be easier to stub or swap-in another library that provides the same interface.</p>
<p>Overall it feels much simpler and much more Ruby-ish.</p>
<p>In addition I would propose adding a few extra methods to test for ranges of statuses, for example:</p>
<pre><code>response.client_error?
response.server_error?
</code></pre>
<p>Similar benefits/rationale.</p>
<a name="IMPLEMENTATION"></a>
<h1 >IMPLEMENTATION<a href="#IMPLEMENTATION" class="wiki-anchor">¶</a></h1>
<p>I have already been using methods like this in some gems, and I have created a "proof of concept" implementation which monkey-patches Net::HTTP to test the idea out. Available here:</p>
<pre><code>http://rubygems.org/gems/net-http-predicates
https://github.com/timcraft/net-http-predicates
</code></pre>
<p>I can think of various different ways to implement a patch, so if this feature would be accepted into ruby-trunk I would welcome suggestions/guidance on a preferred implementation.</p>
<p>These changes would be backwards compatible and straightforward to provide as a backport, either in the backports library/gem or as a standalone gem.</p>
<a name="DISCUSSION"></a>
<h1 >DISCUSSION<a href="#DISCUSSION" class="wiki-anchor">¶</a></h1>
<p>Before discussing how to implement this patch I would like to get people's thoughts on the idea/proposal, and some indication of whether this could be accepted into ruby-trunk (or not). If it would be accepted I'm happy to write/submit the patch itself.</p> Ruby master - Bug #9010 (Assigned): ./configure --prefix= cannot handle directories with spaceshttps://bugs.ruby-lang.org/issues/90102013-10-10T07:50:41Zpostmodern (Hal Brodigan)postmodern.mod3@gmail.com
<p>It appears that the linking task fails when the --prefix value contains spaces.</p>
<p>Steps to Reproduce:</p>
<ol>
<li>./configure --prefix="$HOME/foo bar"</li>
<li>make</li>
</ol>
<p>Expected Result: success<br>
Actual Result:</p>
<p>make[2]: Entering directory <code>/home/hal/src/ruby-2.0.0-p247' linking ruby gcc: error: bar/lib: No such file or directory gcc: error: bar/lib: No such file or directory make[2]: *** [ruby] Error 1 make[2]: Leaving directory </code>/home/hal/src/ruby-2.0.0-p247'<br>
make[1]: *** [all] Error 2<br>
make[1]: Leaving directory `/home/hal/src/ruby-2.0.0-p247'<br>
make: *** [build-ext] Error 2</p> Ruby master - Feature #8959 (Assigned): Allow top level prependhttps://bugs.ruby-lang.org/issues/89592013-09-27T06:24:27Zkyrylo (Kyrylo Silin)silin@kyrylo.org
<p>Since <code>include</code> works on top level, it's reasonable to enable top level<br>
<code>prepend</code> as well.</p>
<p>I've already added a patch (it was partially merged by nobu): <a href="https://github.com/ruby/ruby/pull/395" class="external">https://github.com/ruby/ruby/pull/395</a></p> Ruby master - Feature #8839 (Assigned): Class and module should return the class or module that w...https://bugs.ruby-lang.org/issues/88392013-08-31T02:57:19Zheadius (Charles Nutter)headius@headius.com
<p>With the change for <a href="https://bugs.ruby-lang.org/issues/3753" class="external">https://bugs.ruby-lang.org/issues/3753</a>, "def" forms now return the symbolic name of the method defined. Because class and module bodies just return the last expression in their bodies, this means they will now usually end up returning a symbol for the last method defined. This does not seem useful or correct.</p>
<p>I think class and module should return a reference to the class or module just opened. This would make the return value useful and consistent.</p> Ruby master - Feature #8460 (Assigned): PATCH: optparse: add `keep_unknown` optionhttps://bugs.ruby-lang.org/issues/84602013-05-29T20:39:13Zfelipec (Felipe Contreras)felipe.contreras@gmail.com
<p>Currently people have to do very convoluted tricks, essentially making<br>
it impossible for optparse to keep unknown options.</p>
<p>The safest and cleanest way is to do it in the code itself.</p>
<p>[1] <a href="http://www.ruby-forum.com/topic/88081" class="external">http://www.ruby-forum.com/topic/88081</a><br>
[2] <a href="http://stackoverflow.com/questions/3642331/can-optparse-skip-unknown-options-to-be-processed-later-in-a-ruby-program" class="external">http://stackoverflow.com/questions/3642331/can-optparse-skip-unknown-options-to-be-processed-later-in-a-ruby-program</a></p> Ruby master - Feature #8295 (Assigned): Float や Rational から(可能であれば)正確な BigDecimal を生成する機能https://bugs.ruby-lang.org/issues/82952013-04-19T17:26:29Zmetanest (Makoto Kishimoto)
<p>=begin<br>
たまに、Float を正確に表現する BigDecimal が欲しいことがあります。</p>
<p>(有効数字の考え方からは邪道ですが。また普通は printf の "%a" による<br>
十六進表現で用が足りることも多いでしょう)</p>
<p>十進でも桁数を必要なだけ伸ばせば、普通の 2 進の浮動小数点数なら正確に<br>
表現できます。また、Rational も分母が 2 と 5 以外の約数を持たない場合に<br>
限っては、正確に BigDecimal に変換できます。</p>
<p>そういった場合に、BigDecimal(0.1, nil) のように精度に nil を指定すれば、<br>
正確な変換が行われたら便利だと思います。Rationalについては、任意の n 進法<br>
を指定して正確な文字列表現にできる場合には変換するという機能(たとえば、<br>
Rational(1, 3) は、3 進法で 0.1 です)というのもありうるかと思いますが、<br>
そこまで実装してはいません。</p>
<p>基本的なアイディアを実装したコードは<br>
((<a href="URL:https://gist.github.com/metanest/5418814" class="external">URL:https://gist.github.com/metanest/5418814</a>))<br>
にあります。名前などのインタフェースには検討の必要が残っていると思います。<br>
=end</p> Ruby master - Feature #8126 (Assigned): OpenSSL::SSL::SSLSocket does not define #recv and #send m...https://bugs.ruby-lang.org/issues/81262013-03-20T06:38:27Zpostmodern (Hal Brodigan)postmodern.mod3@gmail.com
<p>OpenSSL::SSL::SSLSocket does not define #recv/#send methods and is not compatible with TCPSocket.</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 #7532 (Assigned): Hardcoded compiler locationhttps://bugs.ruby-lang.org/issues/75322012-12-07T17:57:20Zmpapis (Michal Papis)mpapis@gmail.com
<p>Currently RbConfig::CONFIG["CC"] is hardcoded during compilation, this is an issue when compiling ruby that can be run on other machines, ruby used for compilation might be not available on target system.</p>
<p>A good example is Apple OSX, there are multiple ways to get gcc-4.2 for it - considering <a href="https://bugs.ruby-lang.org/issues/5883" class="external">https://bugs.ruby-lang.org/issues/5883</a> GNU GCC is preferred over LLVM clang.</p>
<p>So assuming ruby is compiled on machine A with /usr/bin/gcc4.2 - and moved to machine B with /opt/local/bin/gcc - which both are the same version "i686-apple-darwin11-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)" - just compiled in different paths. Compiling gems with native extensions would fail in that case because of the recorded compiler path.</p>
<p>Please consider changing the line in rbconfig.rb to: CONFIG["CC"] = ENV["CC"] || "..."</p>
<p>It will allow changing compiler after moving ruby. As '--enable-load-relative' is a prerequisite for moving rubies it could be also used as a switch for adding that change as I can understand there might be a need for preserving compiler used for building ruby so the same is used for building gems.</p>
<p>This trick is used by default in MagLev <a href="http://maglev.github.com/" class="external">http://maglev.github.com/</a></p> Ruby master - Feature #7518 (Assigned): Fiddle::Pointer#to_str and Fiddle::Pointer#to_int should ...https://bugs.ruby-lang.org/issues/75182012-12-05T23:38:35Zngoto (Naohisa Goto)ngotogenome@gmail.com
<p>There are Fiddle::Pointer#to_str and to_int, to be used for implicit conversion to String and Integer, respectively. I think those implicit conversion methods should be removed.<br>
(Note that there are to_s and to_i, explicit conversion to String and Integer, respectively.)</p>
<p>About to_str: Because Fiddle::Pointer is not always a pointer of char *, and careless conversion of invalid pointer to a string would frequently cause SEGV. So, I think implicit conversion to string is very danger and it should be removed.</p>
<p>About to_int: Unlike to_str, pointer arithmetic methods are available in Fiddle::Pointer, but it lacks many methods for treating it as integer, and I think Fiddle::Pointer is not suitable for implicit conversion to integer.</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 #7394 (Assigned): Enumerable#find ifnone parameter could be non-callablehttps://bugs.ruby-lang.org/issues/73942012-11-19T12:36:44Zzzak (zzak _)
<p>from github:<br>
<a href="https://github.com/ruby/ruby/pull/186" class="external">https://github.com/ruby/ruby/pull/186</a></p>
<p>In trunk the <code>Enumerable#find</code> method <code>ifnone</code> parameter has to be callable or <code>nil</code>. I found that sometimes I want to return a simple value without wrapping it in a proc. This pull request adds support for non-callable defaults when no items match.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">a</span> <span class="o">=</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="mi">3</span><span class="p">]</span>
</code></pre>
<p>The current behavior</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">a</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span><span class="nb">proc</span> <span class="p">{</span> <span class="ss">:foo</span> <span class="p">})</span> <span class="p">{</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span> <span class="n">x</span> <span class="o">></span> <span class="mi">3</span> <span class="p">}</span> <span class="c1">#=> :foo</span>
</code></pre>
<p>With patch</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">a</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span> <span class="n">x</span> <span class="o">></span> <span class="mi">3</span> <span class="p">}</span> <span class="c1">#=> 0</span>
</code></pre> Ruby master - Feature #7321 (Assigned): Newton.#nsolve の第 2 引数が複数の役割を持つhttps://bugs.ruby-lang.org/issues/73212012-11-10T16:17:17Zsho-h (Sho Hashimoto)sho-h@netlab.jp
<p>Newton.#nsolve の第 2 引数 x は以下の 2 つの役割を持つようです。</p>
<ul>
<li>探索を開始する点</li>
<li>解を代入</li>
</ul>
<p>newton.rb のコメントにも同じ内容が記述してあるのでわかるといえばわかるのですが、できればそれぞれ分けた方がわかりやすいのではないかと思いました。Newton.#nsolve の戻り値として返すか、引数を追加するのはどうでしょう。</p> Ruby master - Feature #7314 (Assigned): Convert Proc to Lambda doesn't work in MRIhttps://bugs.ruby-lang.org/issues/73142012-11-09T01:30:19Zschneems (Richard Schneeman)
<p>I have code where I need to convert a proc to a lambda (i need to be able to return out of the block). I would expect that passing a proc into a lambda to return a lambda. When I run this code on MRI i do not get the result I would expect</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">my_proc</span> <span class="o">=</span> <span class="nb">proc</span> <span class="p">{</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="n">my_lambda</span> <span class="o">=</span> <span class="nb">lambda</span> <span class="o">&</span><span class="n">my_proc</span>
<span class="n">my_lambda</span><span class="p">.</span><span class="nf">lambda?</span>
</code></pre>
<p>The result is <code>false</code> but I would expect it to be <code>true</code></p>
<p>There is currently a way to turn a proc into a lambda in MRI like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">convert_to_lambda</span> <span class="o">&</span><span class="n">block</span>
<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="n">obj</span><span class="p">.</span><span class="nf">define_singleton_method</span><span class="p">(</span><span class="ss">:_</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="k">return</span> <span class="n">obj</span><span class="p">.</span><span class="nf">method</span><span class="p">(</span><span class="ss">:_</span><span class="p">).</span><span class="nf">to_proc</span>
<span class="k">end</span>
</code></pre>
<p>But this feels like a hack, and is not supported across other implementations. I would expect that passing a proc into a lambda to return a lambda, I believe it is a bug.</p> Ruby master - Feature #6973 (Assigned): Add an #integral? method to Numeric to test for whole-num...https://bugs.ruby-lang.org/issues/69732012-09-04T06:03:43Zregularfry (Alex Young)alex@blackkettle.org
<p>Numeric#integer? checks whether an instance is an Integer. It is often useful to check whether the value of a non-Integer variable is actually a whole number, and the #integer? method doesn't help here.</p>
<p>This patch adds Numeric#integral?, which performs this check.</p> Ruby master - Feature #6857 (Assigned): bigdecimal/math BigMath.E/BigMath.exp R. P. Feynman inspi...https://bugs.ruby-lang.org/issues/68572012-08-11T23:46:18Zroyaltm (Rafał Michalski)
<p>The algorythms to calculate E and exp programmed in BigMath module are the very straightforward interpretation of the series 1 + x + x^2/2! +<br>
x^3/3! + ....<br>
Therefore they are slow.</p>
<p>Try it yourself:</p>
<pre><code> require 'bigdecimal/math'
def timer; s=Time.now; yield; puts Time.now-s; end
timer { BigMath.E(1000) } #-> 0.038848
timer { BigMath.E(10000) } #-> 16.526972
timer { BigMath.E(100000) } #-> lost patience
</code></pre>
<p>That's because every iteration divides 1 by n! and the dividend grows extremely fast.</p>
<p>In "Surely You're Joking, Mr. Feynman!" (great book, you should read it if you didn't already) R. P. Feynman said:</p>
<p>"One day at Princeton I was sitting in the lounge and overheard some mathematicians talking about the series for e^x, which is 1 + x + x^2/2! +<br>
x^3/3! Each term you get by multiplying the preceding term by x and dividing by the next number. For example, to get the next term after x^4/4! you<br>
multiply that term by x and divide by 5. It's very simple."</p>
<p>Yes it's very simple indeed. Why it's not been applied in such a great, modern and popular language? Is it because people just forget about simple solutions today?</p>
<p>Here is a Feynman's optimized version of BigMath.E:</p>
<pre><code> def E(prec)
raise ArgumentError, "Zero or negative precision for E" if prec <= 0
n = prec + BigDecimal.double_fig
y = d = i = one = BigDecimal('1')
while d.nonzero? && (m = n - (y.exponent - d.exponent).abs) > 0
m = BigDecimal.double_fig if m < BigDecimal.double_fig
d = d.div(i, m)
i += one
y += d
end
y
end
</code></pre>
<p>Now, let's put it to the test:</p>
<pre><code> (1..1000).all? {|n| BigMath.E(n).round(n) == E(n).round(n) }
=> true
BigMath.E(10000).round(10000) == E(10000).round(10000)
=> true
</code></pre>
<p>What about the speed then?</p>
<pre><code> timer { E(1_000) } #-> 0.003832 ~ 10 times faster
timer { E(10_000) } #-> 0.139862 ~ 100 times faster
timer { E(100_000) } #-> 8.787411 ~ dunno?
timer { E(1_000_000) } #-> ~11 minutes
</code></pre>
<p>The same simple rule might be applied to BigDecimal.exp() which originally uses the same straightforward interpretation of power series.<br>
Feynman's pure ruby version of BigMath.exp (the ext version seems now pointless anyway):</p>
<pre><code> def exp(x, prec)
raise ArgumentError, "Zero or negative precision for exp" if prec <= 0
x = case x
when Float
BigDecimal(x, prec && prec <= Float::DIG ? prec : Float::DIG + 1)
else
BigDecimal(x, prec)
end
one = BigDecimal('1', prec)
case x.sign
when BigDecimal::SIGN_NaN
return BigDecimal::NaN
when BigDecimal::SIGN_POSITIVE_ZERO, BigDecimal::SIGN_NEGATIVE_ZERO
return one
when BigDecimal::SIGN_NEGATIVE_FINITE
x = -x
inv = true
when BigDecimal::SIGN_POSITIVE_INFINITE
return BigDecimal::INFINITY
when BigDecimal::SIGN_NEGATIVE_INFINITE
return BigDecimal.new('0')
end
n = prec + BigDecimal.double_fig
if x.round(prec) == one
y = E(prec)
else
y = d = i = one
while d.nonzero? && (m = n - (y.exponent - d.exponent).abs) > 0
m = BigDecimal.double_fig if m < BigDecimal.double_fig
d = d.mult(x, m).div(i, m)
i += one
y += d
end
end
y = one.div(y, n) if inv
y.round(prec - y.exponent)
end
(1..1000).all? {|n| exp(E(n),n) == BigMath.exp(BigMath.E(n),n) }
# => true
(1..1000).all? {|n| exp(-E(n),n) == BigMath.exp(-BigMath.E(n),n) }
# => true
(-10000..10000).all? {|n| exp(BigDecimal(n)/1000,100) == BigMath.exp(BigDecimal(n)/1000,100) }
# => true
(1..1000).all? {|n| exp(BigMath.PI(n),n) == BigMath.exp(BigMath.PI(n),n) }
# => true
timer { BigMath.exp(BigDecimal('1').div(3, 10), 100) } #-> 0.000496
timer { exp(BigDecimal('1').div(3, 10), 100) } #-> 0.000406 faster but not that really
timer { BigMath.exp(BigDecimal('1').div(3, 10), 1_000) } #-> 0.029231
timer { exp(BigDecimal('1').div(3, 10), 1_000) } #-> 0.004554 here we go...
timer { BigMath.exp(BigDecimal('1').div(3, 10), 10_000) } #-> 12.554197
timer { exp(BigDecimal('1').div(3, 10), 10_000) } #-> 0.189462 oops :)
timer { exp(BigDecimal('1').div(3, 10), 100_000) } #-> 11.914613 who has the patience to compare?
</code></pre>
<p>Arguments with large mantissa should slow down the results of course:</p>
<pre><code> timer { BigMath.exp(BigDecimal('1').div(3, 1_000), 1_000) } #-> 0.119048
timer { exp(BigDecimal('1').div(3, 1_000), 1_000) } #-> 0.066177
timer { BigMath.exp(BigDecimal('1').div(3, 10_000), 10_000) } #-> 68.083222
timer { exp(BigDecimal('1').div(3, 10_000), 10_000) } #-> 29.439336
</code></pre>
<p>Though still two times faster than the ext version.</p>
<p>It seems Dick Feynman was not such a joker after all. I think he was a master in treating lightly "serious" things and treating very seriously things that didn't matter to anybody else.</p>
<p>I'd write a patch for ext version if you are with me. Just let me know.</p> Ruby master - Feature #6842 (Assigned): Add Optional Arguments to String#striphttps://bugs.ruby-lang.org/issues/68422012-08-07T20:24:20Zwardrop (Tom Wardrop)tom@tomwardrop.com
<p>=begin<br>
One of the very few things I miss from the ol' php days many years ago, was the ability to easily strip arbitrary characters from the ends of string using trim(). Typically, this is whitespace characters, and #strip currently fulfils that use case, but there are also instances where it'd be nice to be able to strip any range of characters from the ends of a string. It goes well with Array#join as often when joining strings with a delimiter, you want to make sure those strings don't already begin or end with that character.</p>
<p>For a full-featured #strip, I'd like to see it have the option of accepting both an Array or String. If a string is provided, each character in that string will be stripped. If an array of strings is given, each element of the array is stripped from the ends of the string - this allows for multi-character delimiters for example. Of course you could go really nuts and supports regex as well (or instead of arrays). To demonstrate the difference...</p>
<pre><code>"<b>bold text</b>".strip("</b>") #=> "old text"
"<b>bold text</b>".strip(["<b>", "</b>"]) #=> "bold text"
"<em><b>bold text</b></em>".strip(["<b>", "</b>", "<em>", "</em>"]) #=> "bold text"
"<em><b>bold text</b></em>".strip(/<\/?.+?>/) #=> "bold text"
</code></pre>
<p>A simple real-world example; this is actually what I was wanting to do right before I came here to raise this feature request, but there's been all kinds of other use cases I've hit in the past:</p>
<pre><code>['some', '/chunked', 'path/'].map{ |v| v.strip('/') }.join('/') #=> "some/chunked/path"
</code></pre>
<p>File#join does something similar, but when you need control over the joining character, this is the way you'd do it.</p>
<p>I've lost count of how many times I've wanted this in Ruby, and there's really no nice workaround. Here's an example on StackOverflow of someone asking how to achieve this stripping behaviour in ruby: <a href="http://stackoverflow.com/questions/3453262/how-to-strip-leading-and-trailing-quote-from-string-in-ruby" class="external">http://stackoverflow.com/questions/3453262/how-to-strip-leading-and-trailing-quote-from-string-in-ruby</a></p>
<p>Obviously, you'd do the same for #lstrip and #rstrip, and all the mutable variants (#strip!, #lstrip!, #rstrip!). Looking forward to others thoughts on this one.<br>
=end</p> Ruby master - Feature #6811 (Assigned): File, Dir and FileUtils should have bang-versions of sing...https://bugs.ruby-lang.org/issues/68112012-07-29T20:34:08Zprijutme4ty (Ilya Vorontsov)prijutme4ty@gmail.com
<p>I found that often write<br>
Dir.mkdir(folder) unless Dir.exist? folder<br>
and similar code for rm, rm_rf and so on<br>
We can simply make bang-versions like<br>
def Dir.mkdir!(folder, permissions=0744)<br>
Dir.mkdir(folder, permissions) unless Dir.exist? folder</p>
<a name="or-another-alternative-Dirmkdirfolder-permissions-rescue-false"></a>
<h1 >or another alternative Dir.mkdir(folder, permissions) rescue false<a href="#or-another-alternative-Dirmkdirfolder-permissions-rescue-false" class="wiki-anchor">¶</a></h1>
<p>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 #6682 (Assigned): Add a method to return an instance attached by a singleto...https://bugs.ruby-lang.org/issues/66822012-07-01T19:22:05Zryoqun (Ryo Onodera)ryoqun@gmail.com
<p>=begin<br>
Currently, there is no easy way to get the attached instance from a singleton class. For MRI, we have to resort to writing an C extension. So it'll be useful to add an instance method to Class to return the attached instance if the given class object is a singleton class.</p>
<p>I'll show what I want in the code-wise with the following code snippet:</p>
<p>text = "I love Ruby."<br>
klass = text.singleton_class</p>
<a name="gt-ltClassString0x000000027383e8gt"></a>
<h1 >=> #<Class:#<a href="String:0x000000027383e8" class="external">String:0x000000027383e8</a>><a href="#gt-ltClassString0x000000027383e8gt" class="wiki-anchor">¶</a></h1>
<p>klass.singleton_instance # <= This is the new method.</p>
<a name="gt-I-love-Ruby"></a>
<h1 >=> "I love Ruby."<a href="#gt-I-love-Ruby" class="wiki-anchor">¶</a></h1>
<p>String.singleton_instance # <= This should return nil because String isn't a singleton class and there is no singleton instance, rather there will be many instances.</p>
<a name="gt-nil"></a>
<h1 >=> nil<a href="#gt-nil" class="wiki-anchor">¶</a></h1>
<p>As for use cases, in my case, I wanted to create a module to add class methods. And it has some state, so must be initialized properly. And it can equally be used by Class#extend and Class#include like this:</p>
<p>module Countable<br>
attr_reader(:count)</p>
<pre><code>class << self
def extended(extended_class)
p("extending #{extended_class}")
super
initialize_state(extended_class)
end
def included(included_class)
p("including #{included_class}")
super
if included_class.singleton_instance # <= Currently, I can't do this.
initialize_state(included_class.singleton_instance)
end
end
private
def initialize_state(object)
p("initializing state of #{object}")
object.instance_variable_set(:@count, 0)
end
end
</code></pre>
<p>end</p>
<p>class Person<br>
extend(Countable)<br>
end</p>
<p>class Book<br>
class << self<br>
include(Countable)<br>
end<br>
end</p>
<p>p(Person.count)<br>
p(Book.count)</p>
<a name="gt-extending-Person"></a>
<h1 >=> "extending Person"<a href="#gt-extending-Person" class="wiki-anchor">¶</a></h1>
<a name="gt-initializing-state-of-Person"></a>
<h1 >=> "initializing state of Person"<a href="#gt-initializing-state-of-Person" class="wiki-anchor">¶</a></h1>
<a name="gt-including-ClassBook"></a>
<h1 >=> "including #<a href="Class:Book" class="external">Class:Book</a>"<a href="#gt-including-ClassBook" class="wiki-anchor">¶</a></h1>
<a name="gt-initializing-state-of-Book"></a>
<h1 >=> "initializing state of Book"<a href="#gt-initializing-state-of-Book" class="wiki-anchor">¶</a></h1>
<a name="gt-0"></a>
<h1 >=> 0<a href="#gt-0" class="wiki-anchor">¶</a></h1>
<a name="gt-0-2"></a>
<h1 >=> 0<a href="#gt-0-2" class="wiki-anchor">¶</a></h1>
<p>Others wanted this functionality as shown by ((<this stackoverflow page|URL:<a href="http://stackoverflow.com/questions/7053455/given-a-ruby-metaclass-how-do-i-get-the-instance-to-which-it-is-attached%3E" class="external">http://stackoverflow.com/questions/7053455/given-a-ruby-metaclass-how-do-i-get-the-instance-to-which-it-is-attached></a>)). Also, I found several actual C-extensions for this kind of functionality on the wild browsing ((<a search result|URL:<a href="https://github.com/search?q=rb_iv_get+__attached__&repo=&langOverride=&start_value=1&type=Code&language=C%3E" class="external">https://github.com/search?q=rb_iv_get+__attached__&repo=&langOverride=&start_value=1&type=Code&language=C></a>)) on github.</p>
<ul>
<li>((<eigen|URL:<a href="https://github.com/elliottcable/refinery/blob/853dcc2254557200d1d6be4cb9c105e8fa9d01a9/ext/eigen/eigen.c#L12%3E" class="external">https://github.com/elliottcable/refinery/blob/853dcc2254557200d1d6be4cb9c105e8fa9d01a9/ext/eigen/eigen.c#L12></a>))</li>
<li>((<mult|URL:<a href="https://github.com/banister/mult/blob/6a1d0bdd383e7e231c5b7c2c718204dfb6ba28ca/ext/mult/mult.c#L43%3E" class="external">https://github.com/banister/mult/blob/6a1d0bdd383e7e231c5b7c2c718204dfb6ba28ca/ext/mult/mult.c#L43></a>))</li>
</ul>
<p>Thanks for creating a great language. Especially I love its meta-programming capability. I'd wish this feature to lead to better meta-programming capability of Ruby.<br>
=end</p> Ruby master - Feature #6671 (Assigned): File.split_all and File.split_roothttps://bugs.ruby-lang.org/issues/66712012-06-30T04:28:57Ztrans (Thomas Sawyer)
<p>=begin<br>
Is there a method for this already?</p>
<p>File.split_all('a/b/c') #=> ['a','b','c']</p>
<p>If not I propose it be added. I've had need of such more than a few times.</p>
<p>It's too bad that File.split can't do this, as it would make more sense. And the current method be called <code>split_base</code>.</p>
<p>In addition <code>split_root</code> would be helpful.</p>
<p>root, path = File.split_all('a/b/c')<br>
root #=> 'a'<br>
path #=> 'b/c'<br>
=end</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 #6611 (Assigned): Comments requested on implementation of set_parse_funchttps://bugs.ruby-lang.org/issues/66112012-06-20T07:46:26Zcjheath (Clifford Heath)clifford.heath@gmail.com
<p>Folk,</p>
<p>I've implemented Twister, a new mutation testing tool to replace Heckle.<br>
It relies on a new hook into the Ruby parser, in order to modify what the<br>
parser thinks it has seen.</p>
<p>Although I have written C extensions before, there are some aspects of<br>
the Ruby core which I'm unfamiliar with and as a result don't know the right<br>
way to handle. I'd like your comments, suggestions and improvements<br>
please.</p>
<p><a href="https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db" class="external">https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db</a></p>
<p>In particular, I'd like to know the following:</p>
<ol>
<li>Do you prefer that I move the literal strings (which occur once each) to #defined?</li>
</ol>
<p><a href="https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L1R1003" class="external">https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L1R1003</a></p>
<ol start="2">
<li>Will this line of code mess up the GC, and how should I fix that?</li>
</ol>
<p><a href="https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L1R3853" class="external">https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L1R3853</a></p>
<ol start="3">
<li>The set_parse_func is extern though it should be static, but I need to move<br>
the rb_define_global_function out of thread.c. Can someone please tell me where I should<br>
move it to, since there is no Init_Parser?</li>
</ol>
<p><a href="https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L1R9029" class="external">https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L1R9029</a></p>
<p><a href="https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L3R4705" class="external">https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L3R4705</a></p>
<ol start="4">
<li>I think I should change set_parse_func to accept a flags argument and a block,<br>
instead of assuming all flags, and taking a Proc. What are the downsides of using a<br>
block instead of a Proc (does this reduce the number of Bindings that get created)?<br>
How do I change set_parse_func to use a block?</li>
</ol>
<p>The initial implementation of Twister is an extension to RSpec which adds the option<br>
"--twist file-or-dir". It's still a bit rough - it needs to change the reporting on the twisted<br>
runs that follow the first (untwisted) run - but it does prove then concept.</p>
<p>Clifford Heath, Data Constellation, <a href="http://dataconstellation.com" class="external">http://dataconstellation.com</a><br>
Agile Information Management and Design.</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 #6413 (Assigned): Make Dir.entries default to Dir.entries(Dir.pwd)https://bugs.ruby-lang.org/issues/64132012-05-08T22:12:34Zshevegen (Robert A. Heiler)shevegen@gmail.com
<p>Is there a reason why Dir.entries requires one argument?</p>
<p>I think it would be easier and more convenient for the userruby if it would default to the current directory. Like so:</p>
<p>Dir.entries(i = Dir.pwd)</p>
<p>Or is there a reason why this is not done?</p> Ruby master - Feature #6376 (Assigned): Feature lookup and checking if feature is loadedhttps://bugs.ruby-lang.org/issues/63762012-04-29T07:03:40Ztrans (Thomas Sawyer)
<p>$LOADED_FEATURES is useful to know what "files" have been loaded. But it doesn't really tell us what "features" have been loaded. If there where were a way to look-up a load path, without actually loading it then it would be possible to compare that to $LOADED_FEATURES and thus know. e.g.</p>
<pre><code>require 'ostruct'
$LOADED_FEATURES #=> [..., "/home/trans/.local/lib/ry/rubies/1.9.3-p125/lib/ruby/1.9.1/ostruct.rb"]
path = require_path('ostruct') #=> "/home/trans/.local/lib/ry/rubies/1.9.3-p125/lib/ruby/1.9.1/ostruct.rb"
$LOADED_FEATURES.include?(path)
</code></pre>
<p>Of course, it would be nice to also have:</p>
<pre><code>required?('ostruct') #=> true
</code></pre>
<p>These methods could be class methods of special module, if it's important to keep the Kernel more tidy, e.g. <code>Ruby.required?('ostruct')</code>.</p>
<p>I am currently working on a project where I need this (and have a couple of other projects that could use it too) and I've had to implement the whole thing from scratch, which isn't simple, nor fast, nor am I 100% confident that it specs exactly to Ruby's own lookup procedure. So it would be much better if Ruby would expose its lookup functionality.</p> Ruby master - Bug #6360 (Assigned): Debug information build even without requesting ithttps://bugs.ruby-lang.org/issues/63602012-04-26T08:46:44Zluislavena (Luis Lavena)luislavena@gmail.com
<p>Hello,</p>
<p>While working on latest RubyInstaller release for 1.9.3-p194 our team detected a bigger shared library and import library being generated.</p>
<p>After further inspection, we found this commit:<br>
<a href="https://github.com/ruby/ruby/commit/ffdaca1d748804f2b5ca2de612f17cf6c78d351b" class="external">https://github.com/ruby/ruby/commit/ffdaca1d748804f2b5ca2de612f17cf6c78d351b</a></p>
<p>Backported r34840 into ruby_1_9_3 branch</p>
<p>The above change added -ggdb to CFLAGS even when was not provided by debugflags configure option.</p>
<p>The following is the comparison of "make" summary with and without the change:</p>
<p>Current trunk:</p>
<pre>
C:\Users\Luis\Projects\oss\ruby\build32>make
CC = gcc
LD = ld
LDSHARED = gcc -shared
CFLAGS = -O3 -fno-omit-frame-pointer -ggdb -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Werror=pointer-arith -Werror=write-strings -Werror=declaration-after-statement -Werror=implicit-function-declaration
XCFLAGS = -include ruby/config.h -include ruby/missing.h -D_FORTIFY_SOURCE=2 -fno-strict-overflow -fvisibility=hidden -DRUBY_EXPORT
CPPFLAGS = -DFD_SETSIZE=32767 -D_WIN32_WINNT=0x0501 -I. -I.ext/include/i386-mingw32 -I../include -I..
DLDFLAGS = -Wl,--enable-auto-image-base,--enable-auto-import -Wl,--out-implib=libmsvcrt-ruby200.dll.a msvcrt-ruby200.def -Wl,--stack,0x00200000,--enable-auto-import
SOLIBS = msvcrt-ruby200.res.o -lshell32 -lws2_32 -limagehlp
</pre>
<p>Reverting r34840:</p>
<pre>
C:\Users\Luis\Projects\oss\ruby\build32>make
CC = gcc
LD = ld
LDSHARED = gcc -shared -s
CFLAGS = -O3 -fno-omit-frame-pointer -g -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Werror=pointer-arith -Werror=write-strings -Werror=declaration-after-statement -Werror=implicit-function-declaration
XCFLAGS = -include ruby/config.h -include ruby/missing.h -D_FORTIFY_SOURCE=2 -fno-strict-overflow -fvisibility=hidden -DRUBY_EXPORT
CPPFLAGS = -DFD_SETSIZE=32767 -D_WIN32_WINNT=0x0501 -I. -I.ext/include/i386-mingw32 -I../include -I..
DLDFLAGS = -Wl,--enable-auto-image-base,--enable-auto-import -Wl,--out-implib=libmsvcrt-ruby200.dll.a msvcrt-ruby200.def -Wl,--stack,0x00200000,--enable-auto-import
SOLIBS = msvcrt-ruby200.res.o -lshell32 -lws2_32 -limagehlp
</pre>
<p>Notice that -g changed into -ggdb instead.</p>
<p>I think debug symbols shouldn't be compiled unless requested and this is a regression.</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 - Feature #6293 (Assigned): new queue / blocking queueshttps://bugs.ruby-lang.org/issues/62932012-04-14T08:28:58Ztenderlovemaking (Aaron Patterson)tenderlove@ruby-lang.org
<p>Hi,</p>
<p>I'd like to add new Queue objects to ruby. Whenever I use queues, I either use them in a blocking or non-blocking manner only, so I have separated them in to two classes Thread::Queue, and Thread::BlockingQueue.</p>
<p>Other notable differences, these queues:</p>
<ul>
<li>implement <code>poll</code>, which will return a nil if the queue is empty</li>
<li>do not allow <code>nil</code> to be in the queue as it would interfere with <code>poll</code>
</li>
<li>include Enumerable</li>
</ul>
<p>I think these will be a good basis for implementing a Deque, SynchronizedQueue, and PriorityQueue.</p>
<p>I've attached a patch against trunk.</p> Ruby master - Feature #6277 (Assigned): Hash#convert_keyhttps://bugs.ruby-lang.org/issues/62772012-04-11T01:12:20Ztrans (Thomas Sawyer)
<p>=begin<br>
Many times a hash with uniform keys is needed (or is at least preferable) for a particular usecase. To this end I propose ((%Hash#convert_key%)).</p>
<p>h = {}<br>
h.convert_key{ |k| k.to_sym }<br>
h['a'] = 1<br>
h.update('b'=>2)<br>
h #=> {:a=>1, :b=>2}</p>
<p>The idea is similar in concept to ((%#default_proc%)).</p>
<p>Others solutions to fill this need have been tried and used, but almost exclusively are in the form of a new class. Most notable is Rails HashWithIndifferentAccess. But ((%#convert_key%)) has much greater flexibility since keys can be converted to anything.<br>
=end</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 #5970 (Assigned): Add Enumerable#join with same semantics as Array#joinhttps://bugs.ruby-lang.org/issues/59702012-02-05T17:27:39Znow (Nikolai Weibull)now@disu.se
<p>Currently, to join the elements of an Enumerable, you need to call #to_a on the Enumerable and then #join the result. With Enumerable#join one wouldn’t need need to create an intermediate Array.</p> Ruby master - Feature #5764 (Assigned): Net::HTTP should assume HTTP/0.9 on unexpected responseshttps://bugs.ruby-lang.org/issues/57642011-12-15T06:01:34Zmstyer (Mike Styer)michael@styer.net
<p>Currently Net::HTTP.read_status_line throws Net::HTTPBadResponse if the status line does not conform to HTTP/1.1 specifications.</p>
<p>But in cases when the web server implements a request size limit, it may not read HTTP/1.1 trailer after the request URI and may send back an HTTP/0.9 response.</p>
<p>Nginx does this for 414 Request-URI Too Large responses:</p>
<p><a href="http://lxr.evanmiller.org/http/source/http/ngx_http_header_filter_module.c#L95" class="external">http://lxr.evanmiller.org/http/source/http/ngx_http_header_filter_module.c#L95</a><br>
<a href="http://forum.nginx.org/read.php?2,52862,52862" class="external">http://forum.nginx.org/read.php?2,52862,52862</a></p>
<p>Perl's Net::HTTP provides a "laxed" option to read_response_headers() to assume HTTP/0.9 if it can't find an HTTP/1.1 status line. Ruby should provide a similar option.</p> Ruby master - Feature #5749 (Assigned): new method String#match_all neededhttps://bugs.ruby-lang.org/issues/57492011-12-12T18:03:57Zyimutang (Joey Zhou)
<p>The String class should contain an instance method 'match_all', which is a mixture of 'match' and 'scan'.</p>
<p>The method 'scan' is not a very powerful tool, its result(the yielding thing) is just a matched string or an array of captured strings.</p>
<p>p 'a1bc2de3f'.scan(/(.)\d(.)/) # [["a", "b"], ["c", "d"], ["e", "f"]]</p>
<p>If the regex argument contains groups, I even cannot get the whole matched string, and no information about the matched offsets.</p>
<p>So, a 'match_all' is very necessary. It scan the string, finding every matched, and yielding <em>MatchData instance</em> to the following block.</p>
<p>Here's a simple implemention in Ruby:</p>
<p>class String<br>
def match_all(re,i=0)<br>
if block_given?<br>
while m = self.match(re,i)<br>
yield m<br>
i = m.end(0)<br>
end<br>
return self<br>
else<br>
ary = []<br>
while m = self.match(re,i)<br>
ary << m<br>
i = m.end(0)<br>
end<br>
return ary<br>
end<br>
end<br>
end</p>
<p>However, it is not efficient in the 'while m = self.match(re,i)' way, because it scan the string again and again. If string is UTF8-encoded and contains out-of-ASCII characters, I'm afraid getting the start index of it is so expensive.</p>
<p>So, I think a built-in 'match_all' method, which behaves just like 'scan' but yield MatchData, is needed.</p>
<p>Please consider it, thank you!</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 #5654 (Assigned): Introduce global lock to avoid concurrent requirehttps://bugs.ruby-lang.org/issues/56542011-11-21T19:51:02Znahi (Hiroshi Nakamura)nakahiro@gmail.com
<p>=begin<br>
Current implementation of "require" has locks for each file (expanded name from required feature) and serializes file loading from Threads. The first Thread acquires the lock for the file and starts loading. The second Thread waits for acquiring the lock, and when the first Thread release the lock, it acquires the lock, then returns immediately.<br>
This can cause deadlock by cross-require from Threads.</p>
<p>And code that does not properly use "require" could meet several problems;</p>
<ul>
<li>constants can be defined before they're ready for use</li>
<li>classes can be modified while they're being used</li>
<li>global state can be initialized at the same time it's in use</li>
</ul>
<p>Proposal: introduce global (per VM) lock to avoid concurrent file loading by "require" so that only one Thread can call "require" at the same time.</p>
<p>I don't have pros/cons list at this moment. Let's discuss it, too.</p>
<p>Derived from a discussion at <a class="issue tracker-4 status-6 priority-4 priority-default closed" title="Backport: Please backport thread-safe autoloading patch (Rejected)" href="https://bugs.ruby-lang.org/issues/5621">#5621</a> (thread-safe autoload)<br>
=end</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 #5582 (Assigned): Allow clone of singleton methods on a BasicObjecthttps://bugs.ruby-lang.org/issues/55822011-11-07T12:34:13Zthinkerbot (Simon Chiang)simon.a.chiang@gmail.com
<p>Currently I do not know of a way to implement something like 'clone' on a BasicObject subclass. This is as close as I've gotten but as you can see the singleton methods are not propagated to the clone.</p>
<pre><code>require 'test/unit'
class Context < BasicObject
def _singleton_class_
class << self
SINGLETON_CLASS = self
def _singleton_class_
SINGLETON_CLASS
end
end
_singleton_class_
end
def _class_
_singleton_class_.superclass
end
def _extend_(mod)
mod.__send__(:extend_object, self)
end
def _initialize_clone_(orig)
# set variables as needed
end
def _clone_
clone = _class_.allocate
clone._initialize_clone_(self)
_singleton_class_.included_modules.each {|mod| clone._extend_ mod }
clone
end
end
class ContextTest < Test::Unit::TestCase
module A
def a
:a
end
end
def test__clone__inherits_modules
context = Context.new
context._extend_ A
clone = context._clone_
assert_equal :a, clone.a
end
def test__clone__inherits_singleton_methods
context = Context.new
def context.a
:a
end
clone = context._clone_
assert_equal :a, clone.a # fails
end
end
</code></pre>
<p>Is there a way to do this that I don't see? If not, then I request that a way be added - perhaps by allowing the singleton_class to be set somehow.</p>
<p>In my case I am using Context as the context for a dsl where methods write to a target (an instance variable). I want to be able to clone a context such that I can have multiple contexts with the same methods, including extensions and singletons, that write to different targets.</p>
<p>Thank you.</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 #5461 (Assigned): Add pipelining to Net::HTTPhttps://bugs.ruby-lang.org/issues/54612011-10-19T07:37:41Zdrbrain (Eric Hodel)drbrain@segment7.net
<p>=begin<br>
The attached patch adds HTTP/1.1 pipelining support to Net::HTTP.</p>
<p>Pipelining is only performed on HTTP/1.1 servers. Net::HTTP will check if the server supports pipelining by using the first request in the list. The user can override this via setting (({http.pipelining = true})).</p>
<p>If a server does not support pipelining or there is an error during pipelining an error will be raised that contains the requests that not have been delivered yet and the responses that have been received.</p>
<p>The patch includes documentation explaining the fine details.</p>
<p>Example:</p>
<p>requests = []<br>
requests << Net::HTTP::Get.new('/images/bug.png')<br>
requests << Net::HTTP::Get.new('/images/date.png')<br>
requests << Net::HTTP::Get.new('/images/find.png')</p>
<p>http = Net::HTTP.new 'localhost'<br>
http.start do<br>
http.pipeline requests do |req, res|<br>
open File.basename(req.path), 'wb' do |io|<br>
io.write res.body<br>
end<br>
end<br>
end</p>
<p>Implementation notes:</p>
<ul>
<li>The current Net::HTTP tests make it very difficult to test bad behavior by servers. In test/net/http/utils.rb I introduced a method to replace Net::BufferedIO with a subclass that can behave incorrectly.</li>
<li>Net::HTTP#pipeline does not fall back to sending requests one-by-one for HTTP/1.1 servers. I think this is acceptable as the user can use existing Net::HTTP code to send requests one-by-one.</li>
</ul>
<p>=end</p> Ruby master - Feature #5445 (Assigned): Need RUBYOPT -r before ARGV -rhttps://bugs.ruby-lang.org/issues/54452011-10-14T00:47:09Ztrans (Thomas Sawyer)
<p>Libraries given by -r options in RUBYOPT should be loaded before ones in direct command line arguments.</p>
<p>I use a custom load system for development that I have been using for years and it works very well for me. But Ruby has some edge cases that prevents it from being feature complete. One of these is the order in which RUBYOPT is applied vs. -r command line option.</p>
<p>My custom loader is too large to include here, so I will simply demonstrate the problem with simple sample code:</p>
<p>$ cat req.rb<br>
p "Custom Require"</p>
<p>module Kernel<br>
alias :require0 :require</p>
<pre><code>def require(*a)
puts "Kernel#require"
p a
require0(*a)
end
class << self
alias :require0 :require
def require(*a)
puts "Kernel.require"
p a
require0(*a)
end
end
</code></pre>
<p>end</p>
<p>If we load this via RUBYOPT, the result is:</p>
<p>$ RUBYOPT=-r./req.rb ruby -rstringio -e0<br>
Custom Require</p>
<p>But if we load via -r the result is:</p>
<p>$ ruby -r./req.rb -rstringio -e0<br>
Custom Require<br>
Kernel#require<br>
["stringio"]</p>
<p>I would ask that the output of both invocations to be identical.</p>
<p>(Note, the -T option should still allow RUBYOPT to be omitted regardless.)</p> Ruby master - Feature #5434 (Assigned): Allow per-class whitelisting of methods safe to expose th...https://bugs.ruby-lang.org/issues/54342011-10-11T13:11:08Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<p>We have following pull-request.</p>
<p><a href="https://github.com/ruby/ruby/pull/50" class="external">https://github.com/ruby/ruby/pull/50</a></p>
<p>How do you feel? I can merge this if you are OK.</p> Ruby master - Feature #5389 (Assigned): New method Enumerator#iteratehttps://bugs.ruby-lang.org/issues/53892011-10-03T20:25:16Zyimutang (Joey Zhou)
<p>If we want to iterate over the elements of a enumerable object with <em>multiple</em> blocks, we can use the Enumerator class.</p>
<p>A method 'iterate' is required, we can write it in Ruby:</p>
<pre><code>class Enumerator
def iterate
yield_value = self.next
return_value = yield yield_value
self.feed return_value
self
end
end
</code></pre>
<p>Well, here is an example:</p>
<pre><code>array = (1..10).to_a
enum = array.map!
loop do
enum.iterate {|n| n + 10 }
enum.iterate {|n| n * 2 }
enum.iterate {|n| -n }
end
p array # => [11, 4, -3, 14, 10, -6, 17, 16, -9, 20]
</code></pre>
<p>We want to map an array: the 1st element use blk1, the 2nd use blk2, the 3rd use blk3...</p>
<p>I think this Enumerator#iterate method is sometimes useful, so would you please introduce it into the language core?</p> Ruby master - Feature #5310 (Assigned): Integral objectshttps://bugs.ruby-lang.org/issues/53102011-09-13T10:15:48Zmrkn (Kenta Murata)muraken@gmail.com
<p>I believe it is ambiguous what object can behave as an integral number.<br>
I don't think the current use of Object#to_int isn't appropriate for this purpose.</p>
<p>The most understandable example is Float#to_int.<br>
It should raise error for all float values because they always have uncertainty,<br>
but it doesn't and returns an integral part of it.</p>
<p>I propose to change the use of Object#to_int for the next release of Ruby.<br>
I recommend the following specification changes:</p>
<p>(1) Remove to_int method from Float and BigDecimal.<br>
(2) Rational#to_int returns an Integer only if its denominator is 1. Otherwise, it raises an appropriate error.<br>
(3) Complex#to_int returns the result of to_int of its real part only if its imaginary part is exactly zero (0.0 isn't exactly zero).</p>
<p>If anyone have another idea, please give me your comment.</p> Ruby master - Feature #5133 (Assigned): Array#unzip as an alias of Array#transposehttps://bugs.ruby-lang.org/issues/51332011-08-01T18:30:03Zmrkn (Kenta Murata)muraken@gmail.com
<p>Array#zip の逆は Array#transpose なんですけど、<br>
この対応関係が非常に分かり難いなと思いました。</p>
<p>Haskell には zip の逆をやる関数として unzip が用意されています。<br>
unzip という名前は、「zip の逆をやりたい」と思ったときに<br>
(transpose よりは) 思い付きやすい名前だと思います。</p>
<p>ということで Array#unzip を Array#transpose のエイリアスとして<br>
導入してはどうでしょう?</p>
<p>以下パッチです:</p>
<p>diff --git a/array.c b/array.c<br>
index 8caad66..dc411b7 100644<br>
--- a/array.c<br>
+++ b/array.c<br>
@@ -4720,6 +4720,7 @@ Init_Array(void)<br>
rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);<br>
rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);<br>
rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);</p>
<ul>
<li>rb_define_alias(rb_cArray, "unzip", "transpose");<br>
rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);<br>
rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);<br>
rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);</li>
</ul> Ruby master - Feature #5064 (Assigned): HTTP user-agent classhttps://bugs.ruby-lang.org/issues/50642011-07-21T13:10:00Zdrbrain (Eric Hodel)drbrain@segment7.net
<p>Currently there are some problems with Net::HTTP:</p>
<ul>
<li>Too many ways to use (user confusion)</li>
<li>No automatic support for HTTPS (must conditionally set use_ssl)</li>
<li>No automatic support for HTTPS peer verification (must be manually set)</li>
<li>Single-connection oriented</li>
<li>No support for redirect-following</li>
<li>No support for HTTP/1.1 persistent connection retry (RFC 2616 8.1.4)</li>
<li>No automatic support for HTTP proxies</li>
<li>No automatic support for authentication (must be set per-request)</li>
</ul>
<p>Additionally the style of the API of Net::HTTP makes it difficult to take advantage of persistent connections. The user has to store the created connection and manually handle restarting the connection if it has timed out or is closed by the server.</p>
<p>RFC 2616 8.1.1 has a large section explaining the benefits of persistent connections, but while Net::HTTP implements persistent connections they could be easier for users to implement with next work.</p>
<p>I've implemented support for many of these additional features of Net::HTTP in various projects and I'd like Ruby to have the features required to make a useful HTTP user-agent built-in.</p>
<p>The agent should have the following responsibilities:</p>
<ul>
<li>Make or reuse connections based on [host, port, SSL enabled]</li>
<li>Automatically enable SSL for https URIs</li>
<li>Automatically enable SSL peer verification for SSL connections</li>
<li>Limit number of persistent connections per host</li>
<li>Follow redirects</li>
<li>Retry when a persistent connection fails</li>
<li>Automatically configure proxies</li>
<li>Automatically use authentication</li>
<li>Callbacks for various options connect</li>
</ul>
<p>The agent may add the following responsibilities:</p>
<ul>
<li>Default headers for all requests</li>
<li>HTTP cookies</li>
<li>Tracking history</li>
<li>Logging</li>
</ul>
<p>I don't think any of these features are critical as they are implementable by users via callbacks.</p>
<p>The agent would have the following configurable items:</p>
<ul>
<li>Number of connections per host</li>
<li>Depth of redirects followed</li>
<li>Persistent connection retries (none, HTTP/1.1 (default), always)</li>
<li>Proxy host, port, user, password</li>
</ul>
<p>I think the class should be called Net::HTTP::Agent.</p>
<p>Basic use would look something like this:</p>
<p>uris = [<br>
URI('http://example/1'),<br>
URI('http://example/2'),<br>
URI('https://secure.example'),<br>
]</p>
<p>agent = Net::HTTP::Agent.new</p>
<p>uris.map do |uri|<br>
agent.get uri # Returns Net::HTTPResponse<br>
end</p>
<p>For special requests a Net::HTTPRequest could be constructed:</p>
<p>req = Net::HTTP::Get.new uri.request_uri</p>
<a name="do-something-special-with-req"></a>
<h1 >do something special with req<a href="#do-something-special-with-req" class="wiki-anchor">¶</a></h1>
<p>agent.request req</p>
<p>The agent should support GET, POST, etc. directly through API methods. I think the API should look something like this:</p>
<p>def get uri_or_string, query = nil, headers = nil</p>
<a name="Same-for-other-requests-with-no-body"></a>
<h1 >Same for other requests with no body<a href="#Same-for-other-requests-with-no-body" class="wiki-anchor">¶</a></h1>
<h1></h1>
<a name="query-may-be-a-Hash-or-String"></a>
<h1 >query may be a Hash or String<a href="#query-may-be-a-Hash-or-String" class="wiki-anchor">¶</a></h1>
<a name="How-query-param-vs-query-string-in-URI-is-used-is-undecided"></a>
<h1 >How query param vs query string in URI is used is undecided<a href="#How-query-param-vs-query-string-in-URI-is-used-is-undecided" class="wiki-anchor">¶</a></h1>
<p>def post uri_or_string, data, headers = nil</p>
<a name="same-for-other-requests-with-a-body"></a>
<h1 >same for other requests with a body<a href="#same-for-other-requests-with-a-body" class="wiki-anchor">¶</a></h1>
<h1></h1>
<a name="data-may-be-a-String-IO-or-Hash"></a>
<h1 >data may be a String, IO or Hash<a href="#data-may-be-a-String-IO-or-Hash" class="wiki-anchor">¶</a></h1>
<a name="How-data-format-is-chosen-is-undecided"></a>
<h1 >How data format is chosen is undecided<a href="#How-data-format-is-chosen-is-undecided" class="wiki-anchor">¶</a></h1>
<p>SSL options, proxy options, timeouts and similar options should exist on Net::HTTP::Agent and be set on new connections as they are made.</p>
<p>I've implemented most of these features in mechanize as Mechanize::HTTP::Agent. The Agent class in mechanize is bigger than is necessary and would need to be cut-down for inclusion in Ruby as Net::HTTP::Agent</p>
<p><a href="https://github.com/tenderlove/mechanize/blob/master/lib/mechanize/http/agent.rb" class="external">https://github.com/tenderlove/mechanize/blob/master/lib/mechanize/http/agent.rb</a></p>
<p>Mechanize depends on net-http-persistent to provide HTTP/1.1 retry support and connection management:</p>
<p><a href="https://github.com/drbrain/net-http-persistent/blob/master/lib/net/http/persistent.rb" class="external">https://github.com/drbrain/net-http-persistent/blob/master/lib/net/http/persistent.rb</a></p>
<p>Portions of net-http-persistent should be patches of Net::HTTP, for example #idempotent? #can_retry?, #reset and portions of #request. Other parts (connection management) should be moved to Net::HTTP::Agent.</p>
<p>net-http-persistent provides a separate connection list per thread. I would like Net::HTTP::Agent to be multi-thread friendly but implementing this in another way would be fine.</p>
<p>As an addendum, open-uri and mechanize should be written to take advantage of Net::HTTP::Agent on order to guide useful implementation.</p> Ruby master - Feature #4924 (Assigned): mkmf have_header fails with C++ headershttps://bugs.ruby-lang.org/issues/49242011-06-24T12:09:56Zadgar (Michael Edgar)michael.j.edgar@dartmouth.edu
<p>=begin<br>
When a user calls (({have_header('some_cpp_header.h')})), and then header includes a line such as(({ #include })), mkmf will fail.</p>
<p>An example run follows:</p>
<ul>
<li>
<p>extconf.rb</p>
<p>require 'mkmf'<br>
have_library('stdc++')<br>
have_header('BasicBlock.h')<br>
create_makefile('laser/BasicBlock')</p>
</li>
<li>
<p>mkmf.log<br>
have_header: checking for BasicBlock.h... -------------------- no</p>
<p>"gcc -E -I/Users/michaeledgar/.rvm/rubies/ruby-1.9.2-head/include/ruby-1.9.1/x86_64-darwin10.7.0 -I/Users/michaeledgar/.rvm/rubies/ruby-1.9.2-head/include/ruby-1.9.1/ruby/backward -I/Users/michaeledgar/.rvm/rubies/ruby-1.9.2-head/include/ruby-1.9.1 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wshorten-64-to-32 -Wno-long-long -fno-common -pipe conftest.c -o conftest.i"<br>
In file included from conftest.c:3:<br>
./BasicBlock.h:4:18: error: vector: No such file or directory<br>
./BasicBlock.h:5:21: error: exception: No such file or directory<br>
./BasicBlock.h:6:21: error: stdexcept: No such file or directory<br>
checked program was:<br>
/* begin <em>/<br>
1: #include "ruby.h"<br>
2:<br>
3: #include <BasicBlock.h><br>
/</em> end */</p>
</li>
</ul>
<p>The issue here is that the temporary file created to perform the header test is ((%conftest.c%)), not ((%conftest.cc%)) or ((%conftest.cpp%)). Changing the<br>
name of the file and re-running gcc gives success.</p>
<p>In ((%mkmf.rb%)), have_header executes cpp_command, which creates the shell command to run. However, cpp_command uses the constant (({CONFTEST_C = "conftest.c"})). It should use a new constant, (({CONFTEST_CPP = "conftest.cc"})).</p>
<p>I've attached a patch that does this as expected. Tests pass; I'm unsure precisely how to construct<br>
a test case that would be appropriate for the Ruby trunk. There are very few guiding examples in the<br>
existing test suite.</p> Ruby master - Feature #4831 (Assigned): Integer#prime_factorshttps://bugs.ruby-lang.org/issues/48312011-06-06T00:33:11Zmame (Yusuke Endoh)mame@ruby-lang.org
<p>Hello,</p>
<p>lib/prime provides Integer#prime_division, but I always forget the name.<br>
I think that #prime_factors is more suitable. I'd like to hear opinions<br>
of English natives. What do you think?</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@tsg.ne.jp" class="email">mame@tsg.ne.jp</a></p> Ruby master - Feature #4818 (Assigned): Add method marshalable?https://bugs.ruby-lang.org/issues/48182011-06-03T11:07:15Zyimutang (Joey Zhou)
<p>Some objects can not be marshaled. Maybe there should be a method to tell it.</p>
<p>hash = Hash.new {|h,k| k * 2}</p>
<p>this hash can't be marshaled because it has a default proc. If existing such method:</p>
<p>Marshal.marshalable?(hash) #=> method "Marshal.marshalable?"<br>
hash.marshalable? #=> method "Kernel#marshalable?"</p>
<p>If you think the method name hard to spell, maybe get a synonym "dumpable?"</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 #4521 (Assigned): NoMethodError#message may take very long to executehttps://bugs.ruby-lang.org/issues/45212011-03-25T04:59:14Zadiel.mittmann (Adiel Mittmann)adiel@inf.ufsc.br
<p>=begin<br>
When a non-existing method is called on an object, NoMethodError is risen. If you call #message, however, your code may use up all CPU for a very long time (in my case, up to a few minutes).</p>
<p>I narrowed the problem down to this code in error.c (SVN snapshot) in the function name_err_mesg_to_str():</p>
<p>d = rb_protect(rb_inspect, obj, 0);<br>
if (NIL_P(d) || RSTRING_LEN(d) > 65) {<br>
d = rb_any_to_s(obj);<br>
}</p>
<p>The problem is that, for a complex object, #inspect may take very long to execute, only to have its results thrown away because they will be larger than 65 characters.</p>
<p>Of course I can write a #to_s for all my objects, but the point is that I didn't call #to_s or #inspect, I called #message on an exception object, which then takes a few minutes just to return a short string.</p>
<p>Needless to say, this might be easy to spot in a simple example, but once you're writing a web application that suddenly freezes for one minute with no apparent reason, you're all but clueless as to what's going on. (The first time this happened, I didn't even know that something would eventually show up on the screen -- I thought it was an infinite loop).</p>
<p>Here's an example code that shows this behavior:</p>
<p>require 'nokogiri'<br>
class A<br>
def x<br>
@xml = Nokogiri::XML(File.new('baz.xml', 'rb').read())<br>
foo()<br>
end<br>
end<br>
A.new().x()<br>
a.x</p>
<p>Here, the time it takes for Ruby to print out the message that #foo doesn't exist is proportional to the size of baz.xml.</p>
<p>As a comparison, Python doesn't seem to do this. Take the following code:</p>
<p>class Test:<br>
def <strong>str</strong>(self):<br>
return "hello"<br>
a = Test()<br>
print a<br>
print a.x()</p>
<p>If you execute it, this is the result:</p>
<p>hello<br>
Traceback (most recent call last):<br>
File "test.py", line 6, in <br>
print a.x()<br>
AttributeError: Test instance has no attribute 'x'</p>
<p>It uses the method <strong>str</strong> to convert the object to a string when necessary, but doesn't use it when printing out the message stating that the attribute doesn't exist.</p>
<p>One obvious way to fix this would be to always print out the simpler representation given by rb_any_to_s.<br>
=end</p> Ruby master - Feature #4514 (Assigned): #deep_clone and #deep_dup for Objectshttps://bugs.ruby-lang.org/issues/45142011-03-21T19:23:02Zwardrop (Tom Wardrop)tom@tomwardrop.com
<p>=begin<br>
There's often a need to do a deep clone of an object, especially of Hash/Array trees. The typical work around to the lack of this functionality is to Marshall and then Unmarshall (e.g. Marshal::load(Marshal::dump(self)) ), which incurs more overhead than it probably should, and is not very semantic. My suggestion is to either provide #deep_clone and #deep_dup methods on the Object class, or to at least provide equivalent functionality for Hashes and Arrays, such as possibly a #deep_merge method for Hash. The exact implantation is not a large concern of mine; I'll let the experts determine the best method of achieving the desired outcome.<br>
=end</p> Ruby master - Feature #2324 (Assigned): Dir instance methods for relative pathhttps://bugs.ruby-lang.org/issues/23242009-11-02T17:48:30Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<p>なかだです。</p>
<p><a href="http://www.ipa.go.jp/security/fy20/reports/tech1-tg/2_05.html" class="external">http://www.ipa.go.jp/security/fy20/reports/tech1-tg/2_05.html</a> を<br>
みて思い出したんですが、相対パスを使う<code>Dir</code>のインスタンスメソッド<br>
はどうでしょうか。実装はmvmブランチにあります。</p>
<pre><code>$ ./ruby -v -e 'p Dir.open("ext"){|d|d.open("extmk.rb"){|f|f.gets}}'
ruby 1.9.1 (2008-12-25 mvm 20976) [i686-linux]
"#! /usr/local/bin/ruby\n"
$ mkdir tmp
$ touch tmp/x tmp/y
$ ./ruby -e 'p Dir.open("tmp"){|d|d.unlink("x")}'
0
$ ls tmp/
y
</code></pre>
<p>--<br>
--- 僕の前にBugはない。<br>
--- 僕の後ろにBugはできる。<br>
中田 伸悦</p>