[#35446] [Ruby 1.9 - Bug #4477][Open] Kernel:exec and backtick (`) don't work for certain system commands — Joachim Wuttke <j.wuttke@...>

10 messages 2011/03/07

[#35476] [Ruby 1.9 - Bug #4489][Open] [PATCH] Encodings with /-(unix|dos|mac)\Z/ — "James M. Lawrence" <quixoticsycophant@...>

20 messages 2011/03/10

[#35552] [Ruby 1.9 - Feature #4523][Open] Kernel#require to return the path of the loaded file — Alex Young <alex@...>

14 messages 2011/03/24

[#35565] [Ruby 1.9 - Feature #4531][Open] [PATCH 0/7] use poll() instead of select() in certain cases — Eric Wong <normalperson@...>

33 messages 2011/03/28

[#35566] [Ruby 1.9 - Feature #4532][Open] [PATCH] add IO#pread and IO#pwrite methods — Eric Wong <normalperson@...>

12 messages 2011/03/28

[#35586] [Ruby 1.9 - Feature #4538][Open] [PATCH (cleanup)] avoid unnecessary select() calls before doing I/O — Eric Wong <normalperson@...>

9 messages 2011/03/29

[ruby-core:35543] Re: NoMethodError#message may take very long to execute

From: Adiel Mittmann <adiel@...>
Date: 2011-03-23 15:17:37 UTC
List: ruby-core #35543
Hi,

Should I report the bug I described a few days ago somewhere else? Or
is it considered a non-issue that should be left behind?

On Fri, Mar 18, 2011 at 07:53:14AM +0900, Adiel Mittmann wrote:
> Hello,
> 
> 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).
> 
> I narrowed the problem down to this code in error.c (SVN snapshot) in the function 
> name_err_mesg_to_str():
> 
>             d = rb_protect(rb_inspect, obj, 0);
>             if (NIL_P(d) || RSTRING_LEN(d) > 65) {
>                 d = rb_any_to_s(obj);
>             }
> 
> 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.
> 
> 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.
> 
> 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).
> 
> Here's an example code that shows this behavior:
> 
> <snip>
> require 'nokogiri'
> class A
>   def x
>     @xml = Nokogiri::XML(File.new('baz.xml', 'rb').read())
>     foo()
>   end
> end
> A.new().x()
> a.x
> </snip>
> 
> 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.
> 
> As a comparison, Python doesn't seem to do this. Take the following code:
> 
> <snip>
> class Test:
>     def __str__(self):
>         return "hello"
> a = Test()
> print a
> print a.x()
> </snip>
> 
> If you execute it, this is the result:
> 
> <output>
> hello
> Traceback (most recent call last):
>   File "test.py", line 6, in <module>
>     print a.x()
> AttributeError: Test instance has no attribute 'x'
> </output>
> 
> It uses the method __str__ 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.
> 
> One obvious way to fix this would be to always print out the simpler
> representation given by rb_any_to_s.
> 
> -- 
> Adiel Mittmann

In This Thread