“堆栈级别太深"“define_generate_prefix"中的Rails 5 [英] "stack level too deep" Rails 5 in "define_generate_prefix"

查看:82
本文介绍了“堆栈级别太深"“define_generate_prefix"中的Rails 5的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I get random crashes (Rails will no longer run), log as follows:

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 小时后才会发生.

This only started occurring after upgrading to Rails 5 and occurs more often on systems with less main memory. It's hard to debug because it is very random, occurring usually only after the app has been running for about 24 hours.

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

The overflow happens in actionpack here: 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.

Have tried various ruby versions, currently using ruby 2.5.5p157 with nginx 1.17.3 and Phusion Passenger 6.0.4.

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

Has anybody seen anything similar? If I could replicate it at will I could possibly debug myself, but being the random nature makes it tricky. Any ideas on how to even approach such a problem?

更新:这似乎与此问题非常相似(似乎尚未得到解答):堆栈级别也是如此深 (SystemStackError) 动作包

Update: This seem very similar to this issue (which seems to have not been answered): Stack level too deep (SystemStackError) actionpack

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

Update 2 I now see that any mounted Engine causes the call to define_generate_prefix, for example a typical config/routes.rb with mounted Engine:

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

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

In the mount method there will be a call to define_generate_prefix which in turn extends app.routes with an new find_script_name method. See code here: https://github.com/rails/rails/blob/404ad9e8acf8ab45ae2314050131a00e57e63b40/actionpack/lib/action_dispatch/routing/mapper.rb#L687

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

The end effect is that one supermethod is layered onto the previous over and over with each mount call. Eventually the system has a stack overflow when find_script_name is called by url_for. This seems inevitable

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

However, I can't be the first one to see this, so I'm sure there is something wrong with my understanding. But what?

推荐答案

TL;DR 对问题的回答是:

The TL;DR answer to the problem turned out to be:

不要在挂载的引擎中调用Rails.application.reload_routes!.

更长的解释是,当你有一个挂载的 Rails 引擎时调用 reload_routes! 会导致 mount 方法在 actionpack/lib/action_dispatch/routing 中被调用/mapper.rb 最终导致 app.routes 被一遍遍地扩展(find_script_name),每次你调用 reload_routes!代码>.在某些时候,您很可能会使用 url_for 助手,而这又将在您的 find_script_name 方法层中调用 super 和你会得到一个 stack too deep 错误.

The longer explanation is that calling reload_routes! when you have a mounted Rails Engine leads to the mount method being called in actionpack/lib/action_dispatch/routing/mapper.rb which eventually leads to app.routes being extended (find_script_name) over and over, for every time you call reload_routes!. The at some point you are highly likely to use the url_for helper and this in turn is going to call super inside your layers of find_script_name methods and you will get a stack too deep error.

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

This is possibly a Rails 5 bug and seems to be repeated in Rails 6, so I'll see if I should raise an issue on Github.

这篇关于“堆栈级别太深"“define_generate_prefix"中的Rails 5的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆