Ruby 1.9.2中机架级的SystemStackError,而不是1.8.7

我被引入遗留代码库,将它从Rails 2.4 / Ruby 1.8.7升级到Rails 3.1 / Ruby 1.9.2。 在这样做的过程中,我发现了一个非常有趣的问题,需要花费3天才能弄明白。 我想把它放在这里,为其他人看到问题给它一些谷歌果汁,并提出问题: 为什么?

基本上,我在运行我的应用程序时在Rack级别看到了SystemStackError 。 在错误发生之前我无法获得任何请求,并且因为我的代码从未被触及而无法调试它。 在开发模式下,我可以看到很多站点,然后在数据库被命中时突然得到SystemStackError 。 所以我认为这是一种懒惰加载。

切换到生产模式,第一个请求发生exception。 服务器正常启动,但没有请求通过,我的代码没有被触及。

快进太多小时,我跟踪回溯到Rails中的循环( 完整要点 ):

 /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/action_dispatch/routing/url_for.rb:102:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/action_controller/metal.rb:140:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/abstract_controller/rendering.rb:74:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/abstract_controller/layouts.rb:301:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/action_dispatch/routing/url_for.rb:103:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/action_controller/metal.rb:140:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/abstract_controller/rendering.rb:74:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/abstract_controller/layouts.rb:301:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/action_dispatch/routing/url_for.rb:103:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/action_controller/metal.rb:140:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/abstract_controller/rendering.rb:74:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/abstract_controller/layouts.rb:301:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/action_dispatch/routing/url_for.rb:103:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/action_controller/metal.rb:140:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/abstract_controller/rendering.rb:74:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/abstract_controller/layouts.rb:301:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/action_dispatch/routing/url_for.rb:103:in `initialize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/action_controller/metal.rb:238:in `new' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/action_controller/metal.rb:238:in `block in action' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/action_dispatch/routing/route_set.rb:71:in `call' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/action_dispatch/routing/route_set.rb:71:in `dispatch' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/action_dispatch/routing/route_set.rb:35:in `call' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/rack-mount-0.8.3/lib/rack/mount/route_set.rb:152:in `block in call' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/rack-mount-0.8.3/lib/rack/mount/code_generation.rb:96:in `block in recognize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/rack-mount-0.8.3/lib/rack/mount/code_generation.rb:68:in `optimized_each' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/rack-mount-0.8.3/lib/rack/mount/code_generation.rb:95:in `recognize' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/rack-mount-0.8.3/lib/rack/mount/route_set.rb:141:in `call' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/actionpack-3.1.6/lib/action_dispatch/routing/route_set.rb:538:in `call' /Users/john/.rvm/gems/ruby-1.9.2-p320@qstream-ruby19/gems/omniauth-1.1.0/lib/omniauth/builder.rb:48:in `call' ... 

我们在这里看到的是系统从metal.rb循环到url_for.rblayouts.rbrendering.rbmetal.rburl_for.rb

经过相当大的努力,我将其跟踪到模型文件顶部的下一行( 如此 ):

 include ActionView::Helpers::UrlHelpers 

注意,这不在类中,它在模块级别。

有趣的是, 这适用于Ruby 1.8.7,但在Ruby 1.9.2中导致SystemStackError

我创建了一个Github存储库来说明这种行为 。

如果您获取此存储库并运行ruby18分支,则可以加载页面。 如果你运行ruby19分支,你会在任何请求上得到一个SystemStackError(加载Widget的任何请求,在生产中运行它并且它不会被延迟加载)。

那么,有谁知道为什么?

我的意思是,我认为它与Ruby 1.9加载模块的方式有关,因为它似乎不是由Rails核心引起的问题。 我主要担心的问题是这是否只是由代码库中的惰性编程实践引起的一个深奥的问题,或者它是否是指向更深层次问题的指针,无论是在Ruby还是Rails中。

这看起来像Bug 3144 ,说直接引用帮助器。

 Rails.application.routes.url_helpers