Projects

Ticket #142 (closed defect: fixed)

Opened 3 years ago

Last modified 3 years ago

Infinite loop creating new Monitor object

Reported by: dev@… Owned by: lsansonetti@…
Priority: major Milestone: MacRuby 0.4
Component: MacRuby Keywords:
Cc: jamis@…

Description

Can't quite figure out how, but creating a new instance of a Monitor (std ruby lib) creates an infinite loop which eventually falls over with stack too deep. Looks like it's maybe an issue calling super from within a mixin, when the mixin is within a class which has no explicit superclass?

> macruby -v
MacRuby version 0.3 (ruby 1.9.0 2008-06-03) [universal-darwin9.0]

> macruby -rmonitor -e 'Monitor.new'
/Library/Frameworks/MacRuby.framework/Versions/0.3/usr/lib/ruby/1.9.0/monitor.rb:207:in `initialize': stack level too deep (SystemStackError)
	from /Library/Frameworks/MacRuby.framework/Versions/0.3/usr/lib/ruby/1.9.0/monitor.rb:207:in `initialize'
	from /Library/Frameworks/MacRuby.framework/Versions/0.3/usr/lib/ruby/1.9.0/monitor.rb:207:in `initialize'
	from /Library/Frameworks/MacRuby.framework/Versions/0.3/usr/lib/ruby/1.9.0/monitor.rb:207:in `initialize'
	from /Library/Frameworks/MacRuby.framework/Versions/0.3/usr/lib/ruby/1.9.0/monitor.rb:207:in `initialize'
	from /Library/Frameworks/MacRuby.framework/Versions/0.3/usr/lib/ruby/1.9.0/monitor.rb:207:in `initialize'
	from /Library/Frameworks/MacRuby.framework/Versions/0.3/usr/lib/ruby/1.9.0/monitor.rb:207:in `initialize'
	from /Library/Frameworks/MacRuby.framework/Versions/0.3/usr/lib/ruby/1.9.0/monitor.rb:207:in `initialize'
	from /Library/Frameworks/MacRuby.framework/Versions/0.3/usr/lib/ruby/1.9.0/monitor.rb:207:in `initialize'
	 ... 7263 levels...
	from /Library/Frameworks/MacRuby.framework/Versions/0.3/usr/lib/ruby/1.9.0/monitor.rb:207:in `initialize'
	from /Library/Frameworks/MacRuby.framework/Versions/0.3/usr/lib/ruby/1.9.0/monitor.rb:207:in `initialize'
	from -e:1:in `new'
	from -e:1:in `<main>'

Attachments

142.patch Download (2.9 KB) - added by jamis@… 3 years ago.
Rough (very rough) patch that fixes the infinite loop caused by this issue

Change History

Changed 3 years ago by jamis@…

  • cc jamis@… added

Cc Me!

Changed 3 years ago by jamis@…

This can actually be duplicated easily with something like the following:

module A
  def initialize
    super
  end
end

class B
  include A
end

B.new

I ran into this when trying to get Capistrano to run under MacRuby (since Capistrano depends on Net::SSH, which depends on Ruby's Logger, which depends on Monitor, etc.). I've tried digging through MacRuby to figure out where the error is coming from, but my ruby-internals-fu is yet weak. I'll keep digging, but hopefully someone smarter than me can figure this out more quickly. :)

Changed 3 years ago by isc@…

Just ran into the same issue when trying to use the xmlrpc std-lib, the parser instantiation causes an infinite loop on a super call from a mixin.

Changed 3 years ago by lsansonetti@…

  • milestone changed from MacRuby 0.3 to MacRuby 0.4

Changed 3 years ago by jamis@…

Rough (very rough) patch that fixes the infinite loop caused by this issue

Changed 3 years ago by jamis@…

The patch I just uploaded fixes the problem for me, but the implementation is...messy. I'll be happy to clean it up, but I wanted to get sign-off on whether this was even an appropriate way to approach the solution.

Changed 3 years ago by lsansonetti@…

Thanks for the patch Jamis, it clearly demonstrates that the current mixin implementation suffers from problems. I have an idea to rewrite it by duplicating the module class and interposing it into the ancestors chain during include, I think it should fix this problem and also eliminate some of the dirty code paths in the VM.

Changed 3 years ago by jamis@…

Sounds good. I was thinking something along those lines would be cleanest, but I'm not up to speed enough to tackle that. I'll keep hacking. Still trying to get Net::SSH to run under MacRuby. :)

Changed 3 years ago by lsansonetti@…

  • status changed from new to closed
  • resolution set to fixed

So I have been investigating different solutions to re-implement the mixin feature, but I was unsuccessful.

My first attempt was to create intermediate classes and interpose them inside the ancestor chain, but this causes some problem with the 64-bit libobjc runtime (which does not authorize you to change the superclass of NSObject), it requires to allocate a complete class-pair (both the class and its metaclass) every time, and it does not work if you extend a singleton class.

My second attempt was to monkey-patch the libobjc method lookup functionality to also look inside mixed modules at runtime. This was working but I could not make it stable (and also it's really evil). This was just to experiment a potential change that I would submit to the libobjc guys.

My third attempt was the successful one, I basically used a solution very similar to Jamis' patch and removed the unnecessary code paths. When dispatching the super message we no longer forward it to the real superclass but use the Ruby ancestors chain.

The problem should be fixed in r750.

Note: See TracTickets for help on using tickets.