SystemStackError на уровне стойки в Ruby 1.9.2, а не 1.8.7

Меня привлекли устаревшую кодовую базу, чтобы обновить ее с Rails 2.4/Ruby 1.8.7 до Rails 3.1/Ruby 1.9.2. Делая это, я обнаружил очень интересную проблему, которая потребовалась 3 дня, чтобы попытаться выяснить. Я хотел оставить это здесь, чтобы дать ему немного сока Google, чтобы кто-то еще увидел проблему, и задать вопрос: почему?

В основном я видел SystemStackError на уровне стойки при запуске моего приложения. Я не мог получить какие-либо запросы до того, как возникла ошибка, и не смог отладить ее, потому что мой код никогда не затрагивался. В режиме разработки я смогу увидеть большую часть сайта, а затем внезапно получил бы SystemStackError когда база данных была поражена. Поэтому я подумал, что это что-то ленивое загружается.

Переключитесь в рабочий режим, и исключение произойдет при первом запросе. Сервер запускается нормально, но ни один запрос не проходит, и мой код не был затронут.

Перемотка вперед на слишком много часов, и я отследил трассировку до цикла в 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.rb в layouts.rb в rendering.rb в metal.rb в url_for.rb, так далее

После значительных усилий я отследил это до следующей строки в верхней части файла модели ( например, так):

include ActionView::Helpers::UrlHelpers

Обратите внимание, что это не внутри класса, это на уровне модуля.

Интересно то, что это работает в Ruby 1.8.7, но вызывает SystemStackError в Ruby 1.9.2.

Я создал хранилище Github, иллюстрирующее это поведение.

Если вы возьмете этот репозиторий и запустите ruby18 филиал, вы можете загрузить страницу. Если вы запустите ruby19 В ответ на ветку вы получаете SystemStackError по любому запросу (любой запрос, в который загружен Widget, запустите его в производственном режиме, и он не будет загружен лениво).

Итак, кто-нибудь знает почему?

Я имею в виду, я предполагаю, что это как-то связано с тем, как Ruby 1.9 загружает модули, так как это, похоже, не проблема, вызванная ядром Rails. Мое основное беспокойство вызывает вопрос о том, является ли это просто эзотерической проблемой, вызванной ленивым программированием в кодовой базе, или это указатель на более глубокую проблему, будь то в Ruby или Rails.

1 ответ

Решение

Это похоже на ошибку 3144, говорящую о прямой ссылке на помощника.

Rails.application.routes.url_helpers
Другие вопросы по тегам