使用carrierwave版本时堆栈级别过深

12
我试图使用一个 sidekiq worker,它基本上保存一个图像文件到数据库中(使用carrierwave)。需要保存几个文件,这是从视频文件中提取的关键帧。这就是该工人的作用。
我的图像上传器有几个版本定义,并且如下所示:
class KeyframeUploader < CarrierWave::Uploader::Base

  # ...

  # Keyframe thumbnail sizes
  version :small do
    process resize_to_fill: [180, 180], if: :square?
    process resize_to_fill: [320, 180], if: :not_square?
  end

  version :medium do
    process resize_to_fill: [460, 460], if: :square?
    process resize_to_fill: [640, 460], if: :not_square?
  end

  version :large do
    process resize_to_fill: [720, 720], if: :square?
    process resize_to_fill: [1280, 720], if: :not_square?
  end


  private

    # Checks if image is a square
    def square? file
      img = Magick::Image.read(file.path)
      img[0].columns == img[0].rows
    end

    # Oposite to #square?
    def not_square? file
      !square? file
    end

end

问题是,当我尝试运行我的Sidekiq Worker时,它会抛出Celluloid::FiberStackError: stack level too deep,而唯一解决方法是删除上传程序的版本定义。只有在没有分配给上传程序的任何版本时才能正常工作。

我尝试将保存过程移动到另一个Worker或使用Carrierwave::Backgrounder,但结果始终相同。

你有任何想法可以解决吗?


编辑:我的stracktrace是:

SystemStackError: stack level too deep from /usr/local/rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/irb/workspace.rb:86


FYI,“Stack Level Too Deep”意味着你的某个地方有一个无限循环。 - Richard Peck
2
是的,我知道。问题是我找不到可以拥有它的地方。我感觉这不是我的错,而是CarrierWave的错。 - mbajur
1
你的代码有一个小错误。在31秒内,你将有6帧,在60秒内,你将有3帧。60秒被包含在“else”中……不重要,只是注意一下。 - Ruby Racer
3
您能在这里发布堆栈跟踪吗?另外,您使用的carrierwave/sidekiq版本是哪个? - bbozo
好吧,这很无用,但我已经将其添加到原始问题中(这是我从IRB保存图像时得到的内容)。 - mbajur
显示剩余4条评论
3个回答

40

1
哇塞。救了我的一天! - Andre Zimpel
很高兴你找到了答案。尽管你得到的错误信息中包含 Celluloid::,但这个问题似乎并不属于 celluloid 标签。你同意吗? - digitalextremist
是的,完全正确。已删除Celluloid标签。 - mbajur

1
我会将其翻译为:“我会针对您的工作程序中的for循环进行处理。”同时保留HTML标记。
for i in 1..(frames_to_extract)

你没有增加i,但你似乎在做一个索引循环。我建议使用enumeach_with_index来替换它。
Ruby程序员通常避免使用for循环,因为它很混乱。

这似乎很可能是问题所在... 如果确实是这个问题,你可能会看到一堆相同的“从...中获取截图”的日志条目。 - Brad Werth
当我在 Sidekiq 之外上传图像时,它也会表现得像这样。 - mbajur

0
  1. 检查你的模型,看看是否有一个 after_save 钩子,如果你在该钩子中更新记录,则会回归到无限循环 - 可能你有一个 after_save 创建了制作缩略图的作业,然后存储这些缩略图会启动另一个作业。
  2. 检查线程安全问题,你使用的任何 gem 是否列在 这里?
  3. 检查堆栈跟踪,你能看到哪些行在重复吗?
  4. 当你不使用 sidekiq 处理文件时,错误是否存在?
  5. 问题总是发生还是只在负载下发生?
  6. Ruby 2.1 中的 RMagick bug - https://github.com/rmagick/rmagick/issues/100
  7. ...

是的,如果我没有使用Sidekiq进行处理,那个错误也会出现。堆栈跟踪已添加到原始问题中。 - mbajur
你是如何触发后处理的?通过回调函数吗?另外,你看过这个网址吗:http://stackoverflow.com/questions/18774686/stack-level-too-deep-when-processing-carrierwave-image-versions-in-nested-form?rq=1?这可能是一个后处理库的错误,你用什么来调整图像大小?能否发布Gemfile.lock文件? - bbozo
是的,我看过那个帖子,但我一直都在使用rmagick而没有遇到任何问题,我希望能保持这种状态。Gemfile.lock: https://gist.github.com/f859f467755ba6b82335 。至于触发后处理 - 我不确定如何回答,我是按照carrierwave自述文件中的常规方式来触发它们的。 - mbajur
mbajur,据我所知,您使用的RMagick版本存在错误https://github.com/rmagick/rmagick/issues/100,请尝试使用不同的后处理库来测试您的代码是否正常工作。如果可以,请尝试更改RMagick版本和/或Ruby版本,直到您的代码正常工作。如果仍然无法解决问题,请等待rmagick团队修复我提供的问题。 - bbozo
好的,问题已解决。我已经发布了一个带有解释的答案。感谢您的支持! - mbajur

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接