mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	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
This commit is contained in:
		
							parent
							
								
									2172b44898
								
							
						
					
					
						commit
						c02fa39463
					
				
					 5 changed files with 106 additions and 3 deletions
				
			
		|  | @ -1,3 +1,12 @@ | |||
| Fri Oct 31 22:19:30 2014  Akinori MUSHA  <knu@iDaemons.org> | ||||
| 
 | ||||
| 	* 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 | ||||
| 
 | ||||
| Fri Oct 31 21:33:17 2014  Akinori MUSHA  <knu@iDaemons.org> | ||||
| 
 | ||||
| 	* test/digest/test_digest.rb: Drop #!.  This no longer runs | ||||
|  |  | |||
							
								
								
									
										5
									
								
								NEWS
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								NEWS
									
										
									
									
									
								
							|  | @ -128,6 +128,11 @@ with all sufficient information, see the ChangeLog file. | |||
| === Stdlib updates (outstanding ones only) | ||||
| 
 | ||||
| * Digest | ||||
| 
 | ||||
|   * Digest() 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::*. | ||||
|   * Digest::HMAC has been removed just as previously noticed. | ||||
| 
 | ||||
| * Etc | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
							
								
								
									
										10
									
								
								test/digest/digest/foo.rb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								test/digest/digest/foo.rb
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| module Digest | ||||
|   Foo = nil | ||||
| 
 | ||||
|   sleep 0.2 | ||||
| 
 | ||||
|   remove_const(:Foo) | ||||
| 
 | ||||
|   class Foo < Class | ||||
|   end | ||||
| end | ||||
|  | @ -208,4 +208,65 @@ module TestDigest | |||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   class TestDigestParen < Test::Unit::TestCase | ||||
|     def test_sha2 | ||||
|       assert_separately(%w[-rdigest], <<-'end;') | ||||
|         assert_nothing_raised { | ||||
|           Digest(:SHA256).new | ||||
|           Digest(:SHA384).new | ||||
|           Digest(:SHA512).new | ||||
|         } | ||||
|       end; | ||||
|     end | ||||
| 
 | ||||
|     def test_no_lib | ||||
|       assert_separately(%w[-rdigest], <<-'end;') | ||||
|         class Digest::Nolib < Digest::Class | ||||
|         end | ||||
| 
 | ||||
|         assert_nothing_raised { | ||||
|           Digest(:Nolib).new | ||||
|         } | ||||
|       end; | ||||
|     end | ||||
| 
 | ||||
|     def test_no_lib_no_def | ||||
|       assert_separately(%w[-rdigest], <<-'end;') | ||||
|         assert_raise(LoadError) { | ||||
|           Digest(:Nodef).new | ||||
|         } | ||||
|       end; | ||||
|     end | ||||
| 
 | ||||
|     def test_race | ||||
|       assert_separately(['-rdigest', "-I#{File.dirname(__FILE__)}"], <<-'end;') | ||||
|         assert_nothing_raised { | ||||
|           t = Thread.start { | ||||
|             sleep 0.1 | ||||
|             Digest(:Foo).new | ||||
|           } | ||||
|           Digest(:Foo).new | ||||
|           t.join | ||||
|         } | ||||
|       end; | ||||
|     end | ||||
| 
 | ||||
|     def test_race_mixed | ||||
|       assert_separately(['-rdigest', "-I#{File.dirname(__FILE__)}"], <<-'end;') | ||||
|         assert_nothing_raised { | ||||
|           t = Thread.start { | ||||
|             sleep 0.1 | ||||
|             Digest::Foo.new | ||||
|           } | ||||
|           Digest(:Foo).new | ||||
|           begin | ||||
|             t.join | ||||
|           rescue NoMethodError, NameError | ||||
|             # NoMethodError is highly likely; NameError is listed just in case | ||||
|           end | ||||
|         } | ||||
|       end; | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 knu
						knu