From: knu@... Date: 2014-10-31T13:09:51+00:00 Subject: [ruby-core:66034] [ruby-trunk - Bug #9494] [Assigned] Race condition in autoload of Digest::SHA256, etc. Issue #9494 has been updated by Akinori MUSHA. Status changed from Open to Assigned Assignee set to Akinori MUSHA Hi, Thanks for the patch, but this change is hardly acceptable because it unconditionally increases memory consumption just for solving a problem under a multi-threaded environment. The problem is unavoidable as long as you rely on a constant lookup, because constants defined in a module becomes immediately visible to other threads and there is virtually no way to prevent other threads that refer to the constant from using it before the module finishes initialization. One way to fix it is preload 'digest/*' on application boot just as you said, but I can imagine there will be a situation where this is not acceptable. So, to mitigate the problem under a multi-threaded environment, I'm going to turn `Digest()` into a thread-safe function by making `Digest(:FOO)` always call `require 'digest/foo'` before returning `Digest::FOO`. This is for use in a situation when threads are involved. You say `Digest(:FOO)` instead of `Digest::FOO` and it's thread-safe. What do you think? ---------------------------------------- Bug #9494: Race condition in autoload of Digest::SHA256, etc. https://bugs.ruby-lang.org/issues/9494#change-49753 * Author: Conrad Irwin * Status: Assigned * Priority: Normal * Assignee: Akinori MUSHA * Category: ext * Target version: * ruby -v: 2.0.0p247 * Backport: 1.9.3: UNKNOWN, 2.0.0: UNKNOWN, 2.1: UNKNOWN ---------------------------------------- At the moment the digest extension uses const_missing to implement autoload. Unfortunately there's a race condition: another thread can run after the constant is defined, but before it is initialized. (http://git.io/YW3bbA) There's a minimal test case here: http://git.io/5umBqQ ��� this was happening to us regularly in production because each sidekiq worker would race to create a hash. The work around we have deployed is to require digest/sha2.so pre-emptively. And the attached patch does that. An alternative solution would be to use `autoload`, but that is deprecated; or to change the way meta-data is stored for Digest classes so that it can be accessed immediately. There's no way to use a mutex inside const_missing to fix this, because the bug is that the constant becomes not-missing before it is fully defined. ---Files-------------------------------- require-digest-upfront.patch (1006 Bytes) -- https://bugs.ruby-lang.org/