【问题标题】:Can the origin of "SystemStackError: stack level too deep" be identified without a full stack trace?可以在没有完整堆栈跟踪的情况下识别“SystemStackError:堆栈级别太深”的起源吗?
【发布时间】:2011-12-06 19:29:52
【问题描述】:

我在 Heroku Bamboo MRI (Ruby) 1.9.2 上的 Rails 3.0.9 上运行 Spree 0-60-stable

在 2011 年 12 月 3 日星期六或前后的某个时间,我开始在控制器中收到“SystemStackError(堆栈级别太深)”消息,这些消息之前没有引发该错误。自 11 月 28 日以来,我没有重新编译过 slug。我首先尝试重新启动我的网络进程,但无济于事。从那以后,我做了一个名义上的更改(我的 Gemfile 中的一行空白),所以我可以重新编译并推动它。不用找了。我仍然收到错误消息。我查看了我可能迁移到的可用堆栈,但除了我在竹 mri-1.9.2 上的堆栈之外,没有其他堆栈明确支持我的应用正在使用的 ruby​​ 版本。

错误(根据 Heroku 支持)是:

ActionView::Template::Error(堆栈级别太深)

他们接着说,“这意味着您的模板中有一些东西正在进行可能的递归调用。虽然缺少代码更改可能表明我们有一些奇怪的行为,但也有可能发生了一些变化在您的数据库中,或者某些基于时间的东西会导致行为发生变化。在任何一种情况下,完整的堆栈跟踪都会有所帮助。您是否使用 Airbrake 或 Exceptional 来捕获此错误并确定来源?”

我已经添加了 Airbrake (Hoptoad) 和 Exceptional 来检查它们在堆栈跟踪方面可能显示的内容。两者都提供相同的文件/行参考,但没有更多信息:

.bundle/gems/ruby/1.9.1/gems/actionpack-3.0.9/lib/action_controller/metal/rescue.rb:19

这似乎不是很有帮助,因为它是救援本身,而不是实际触发它的任何代码行,我只有最外层的上下文。我在几个地方看到了同样的错误:

总结一下我的问题:

  1. 我没有更改我的代码,并且问题“突然出现”。
  2. 如果是数据更改,例如管理员中的设置,是什么?
  3. 由于缺少完整的堆栈跟踪,故障排除变得困难。

最后,我的问题:

如果没有完整的堆栈跟踪,是否可以识别“SystemStackError:堆栈级别太深”的起源?

非常感谢您的任何帮助。

【问题讨论】:

    标签: ruby-on-rails-3 heroku stack-trace spree


    【解决方案1】:

    在这种情况下,我会使用“printf 调试”。在控制器和模板代码的各个点添加log.info "got to here 1"(2、3、4 等)。

    然后重现错误。 然后检查日志并查看哪些语句被记录/没有被记录 - 因此您没有访问的代码部分以及是否有任何部分无休止地重复......

    并且您至少已将问题范围缩小到代码的哪一部分。

    【讨论】:

    • 谢谢塔林。我要试试这个。
    • 我在结帐控制器中添加了以下行:logger.debug "---------------------------- in CheckoutController" 和其他类似的行。但是,我在日志中没有看到任何内容。 heroku config给我:LOG_LEVEL => DEBUG
    • 如果这是你的控制器代码中的第一行(即没有首先调用授权的东西)那么问题可能出在 gem/plugin 加载中......这比我能做的更黑魔法从这里帮助你。
    • 事实证明,这是其中一个模型中的循环定义。 Spree 允许由其他区域定义一个区域,并且其中一位管理员使用自己定义了一个区域,这应该是不允许的,但不是。仍然......我从来没有看到我的任何调试输出。很奇怪。
    【解决方案2】:

    SystemStackError 通常是由某些递归方法直接或间接调用自身引起的。这要么是由创建无限递归的错误引起的,要么是由递归发生的某些操作引起的,因此仅适用于有限大小的数据。

    示例

    class Array
      def size
        return 0 if self.empty?
        1+self[1..-1].size
      end
    end
    

    理论上这是大小的正确实现,但它的堆栈大小与数组大小成线性增长。在我的系统上,此实施失败,SystemStackError for Arrays 大于 8714。

    puts 写入您的代码

    如果您怀疑哪些方法可能导致此问题,请在方法中添加 puts 以生成一些调试输出。如果您看到某个方法的大量输出,您可以假设错误就在该方法附近。

    跟踪所有方法

    使用 ruby​​s 内置挂钩来跟踪所有方法创建。然后自动修改每个新创建的方法以生成一些调试输出。使用所有这些调试信息,您的代码会运行得很慢,但您可能会在跟踪中看到递归的原因。

    【讨论】:

    • 谢谢约翰内斯。我不确定 puts 会起作用,因为这是 Heroku 上的生产应用程序。我的本地开发环境中没有发生同样的错误。您的建议是对“调试、调试、调试”的 +1。这就是我将使用内置记录器工具的方向。再次,非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 2013-10-05
    • 2014-10-25
    • 2017-08-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多