summaryrefslogtreecommitdiff
path: root/ext/digest/lib/digest.rb
diff options
context:
space:
mode:
authorknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-10-31 13:21:51 +0000
committerknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-10-31 13:21:51 +0000
commitc02fa39463a0c6bf698b01bc610135604aca2ff4 (patch)
tree7a5a7384ed322e2d8810c7b78e77b456f78236ed /ext/digest/lib/digest.rb
parent2172b44898a643058eb6a1943943d33635a6db61 (diff)
Make Digest() thread-safe.
* ext/digest/lib/digest.rb (Digest()): This function should now be thread-safe. If you have a problem with regard to on-demand loading under a multi-threaded environment, preload "digest/*" modules on boot or use this method instead of directly referencing Digest::*. [Bug #9494] cf. https://github.com/aws/aws-sdk-ruby/issues/525 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48213 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/digest/lib/digest.rb')
-rw-r--r--ext/digest/lib/digest.rb24
1 files changed, 21 insertions, 3 deletions
diff --git a/ext/digest/lib/digest.rb b/ext/digest/lib/digest.rb
index 5f7ebc2237..ef43c46ac3 100644
--- a/ext/digest/lib/digest.rb
+++ b/ext/digest/lib/digest.rb
@@ -1,6 +1,9 @@
require 'digest.so'
module Digest
+ # A mutex for Digest().
+ REQUIRE_MUTEX = Mutex.new
+
def self.const_missing(name) # :nodoc:
case name
when :SHA256, :SHA384, :SHA512
@@ -76,15 +79,30 @@ end
# call-seq:
# Digest(name) -> digest_subclass
#
-# Returns a Digest subclass by +name+.
+# Returns a Digest subclass by +name+ in a thread-safe manner even
+# when on-demand loading is involved.
#
# require 'digest'
#
# Digest("MD5")
# # => Digest::MD5
#
-# Digest("Foo")
+# Digest(:SHA256)
+# # => Digest::SHA256
+#
+# Digest(:Foo)
# # => LoadError: library not found for class Digest::Foo -- digest/foo
def Digest(name)
- Digest.const_get(name)
+ const = name.to_sym
+ Digest::REQUIRE_MUTEX.synchronize {
+ # Ignore autoload's because it is void when we have #const_missing
+ Digest.const_missing(const)
+ }
+rescue LoadError
+ # Constants do not necessarily rely on digest/*.
+ if Digest.const_defined?(const)
+ Digest.const_get(const)
+ else
+ raise
+ end
end