“堆栈级别太深"“define_generate_prefix"中的Rails 5 [英] "stack level too deep" Rails 5 in "define_generate_prefix"
问题描述
我随机崩溃(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 super
method 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屋!