【问题标题】:"stack level too deep" Rails 5 in "define_generate_prefix"“堆栈级别太深” Rails 5 在“define_generate_prefix”
【发布时间】:2021-01-01 15:55:05
【问题描述】:

我遇到随机崩溃(Rails 将不再运行),记录如下:

I, [2020-09-14T21:50:30.398707 #9732]  INFO -- : [e8eb6ebb-46eb-4d0e-93e2-e5d4fe6a8512] Completed 500 Internal Server Error in 10ms (ActiveRecord: 0.8ms)
F, [2020-09-14T21:50:30.406874 #9732] FATAL -- : [e8eb6ebb-46eb-4d0e-93e2-e5d4fe6a8512]   
F, [2020-09-14T21:50:30.406988 #9732] FATAL -- : [e8eb6ebb-46eb-4d0e-93e2-e5d4fe6a8512] SystemStackError (stack level too deep):
F, [2020-09-14T21:50:30.407014 #9732] FATAL -- : [e8eb6ebb-46eb-4d0e-93e2-e5d4fe6a8512]   
F, [2020-09-14T21:50:30.407158 #9732] FATAL -- : [e8eb6ebb-46eb-4d0e-93e2-e5d4fe6a8512] actionpack (5.2.4.4) lib/action_dispatch/routing/mapper.rb:689:in `block (2 levels) in define_generate_prefix'
[e8eb6ebb-46eb-4d0e-93e2-e5d4fe6a8512] actionpack (5.2.4.4) lib/action_dispatch/routing/mapper.rb:689:in `block (2 levels) in define_generate_prefix'
<REPEATED AROUND 500 TIMES>
[e8eb6ebb-46eb-4d0e-93e2-e5d4fe6a8512] actionpack (5.2.4.4) lib/action_dispatch/routing/mapper.rb:689:in `block (2 levels) in define_generate_prefix'

这只是在升级到 Rails 5 后才开始发生,并且在主内存较少的系统上更常见。很难调试,因为它非常随机,通常仅在应用程序运行大约 24 小时后才会发生。

溢出发生在 actionpack 中: https://github.com/rails/rails/blob/404ad9e8acf8ab45ae2314050131a00e57e63b40/actionpack/lib/action_dispatch/routing/mapper.rb#L689

尝试过各种 ruby​​ 版本,目前使用 ruby​​ 2.5.5p157 和 nginx 1.17.3 和 Phusion Passenger 6.0.4。

有人见过类似的吗?如果我可以随意复制它,我可能会调试自己,但是随机性使它变得棘手。关于如何解决此类问题的任何想法?

更新: 这似乎与这个问题非常相似(似乎没有得到回答):Stack level too deep (SystemStackError) actionpack

更新 2 我现在看到任何挂载的 Engine 都会导致对 define_generate_prefix 的调用,例如带有挂载 Engine 的典型 config/routes.rb:

Rails.application.routes.draw do
  devise_for :admins
  resources :admins
  mount MyEngine::Engine, :at => "/", :as => "my_engine"
end

在 mount 方法中将调用define_generate_prefix,而app.routes 又使用新的find_script_name 方法扩展。在此处查看代码:https://github.com/rails/rails/blob/404ad9e8acf8ab45ae2314050131a00e57e63b40/actionpack/lib/action_dispatch/routing/mapper.rb#L687

最终效果是一个 super 方法随着每个 mount 调用一遍又一遍地叠加到前一个方法上。最终,当find_script_nameurl_for 调用时,系统会发生堆栈溢出。这似乎是不可避免的

但是,我不是第一个看到这个的人,所以我确定我的理解有问题。但是什么?

【问题讨论】:

    标签: ruby-on-rails ruby nginx passenger


    【解决方案1】:

    这个问题的 TL;DR 答案原来是:

    不要在已安装的引擎中调用Rails.application.reload_routes!

    更长的解释是,当您安装了 Rails 引擎时调用 reload_routes! 会导致在 actionpack/lib/action_dispatch/routing/mapper.rb 中调用 mount 方法,最终导致 app.routes 一遍又一遍地扩展(find_script_name),每次拨打reload_routes!。在某些时候,您很可能会使用 url_for 帮助程序,而这又会在您的 find_script_name 方法层中调用 super,您将收到 stack too deep 错误。

    这可能是 Rails 5 的错误,并且似乎在 Rails 6 中重复出现,所以我会看看是否应该在 Github 上提出问题。

    【讨论】:

      猜你喜欢
      • 2012-07-24
      • 1970-01-01
      • 2017-08-19
      • 2018-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      相关资源
      最近更新 更多