RuntimeError:在迭代期间无法将新键添加到哈希中

时间:2016-01-04 11:06:29

标签: ruby-on-rails

我的rails应用程序中出现了很多RuntimeError: can't add a new key into hash during iteration错误,但堆栈跟踪并没有指向任何有趣的地方。

https://gist.github.com/tal-moshayov/71e06a83cee236fdedd0

任何提示都将受到高度赞赏

1 个答案:

答案 0 :(得分:0)

[添加锁以使共享散列线程安全]
我遇到了非常类似的问题,问题是一个线程试图修改共享对象(Hash),而其他线程正在迭代它。 最后,我通过添加锁(Mutex)和使用自己的Pure-Ruby concurrent Hash来对其进行排序。

[检查所有线程回溯以查找谁拥有/迭代你的哈希值]
在尝试修改“忙”散列时,您获得的堆栈跟踪问题是,它向您显示您尝试修改散列的地方的函数链,但它没有显示当前正在并行迭代它的人(谁拥有它)!但我找到了通过打印所有当前运行的线程的堆栈跟踪来解决这个问题的方法。这是你如何做到这一点:

# This solution was found in comment by @thedarkone on https://github.com/rails/rails/issues/24627
rescue Object => boom

  # only for your particular exception:
  if boom.message == "can't add a new key into hash during iteration"
    thread_count = 0
    Thread.list.each do |t|
      thread_count += 1
      err_msg += "--- thread #{thread_count} of total #{Thread.list.size} #{t.object_id} backtrace begin \n"
      # Lets see if we are able to pin down the culprit
      # by collecting backtrace for all existing threads:
      err_msg += t.backtrace.join("\n")
      err_msg += "\n---thread #{thread_count} of total #{Thread.list.size} #{t.object_id} backtrace end \n"
    end

    # and just print it somewhere you like:
    $stderr.puts(err_msg)

    raise # always reraise
  end

上面的代码片段即使仅用于教育目的也很有用,因为它可以向您展示(例如X射线)您实际拥有多少线程(相对于您认为有多少线程 - 通常这两个是不同的数字;)< / p>

另见:Concurrent::Hash does not lock on method #each