Skip to content
This repository
Browse code

Fix race in ConnectionPool#checkout

After releasing monitor some connection(s) may appear in pool before monitor is re-aquired.
When this happens we'll wait for connection which is already available.

Signed-off-by: Michael Koziarski <michael@koziarski.com>
  • Loading branch information...
commit 21eb18a70c7a1f08e7e2dc1c5bc17d67e1d14c46 1 parent 4cb3d27
Aliaksey Kandratsenka (aka Aliaksei Kandratsenka) authored October 02, 2008 NZKoz committed October 04, 2008
29  activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -131,21 +131,20 @@ def clear_stale_cached_connections!
131 131
       # Check-out a database connection from the pool.
132 132
       def checkout
133 133
         # Checkout an available connection
134  
-        conn = @connection_mutex.synchronize do
135  
-          if @checked_out.size < @connections.size
136  
-            checkout_existing_connection
137  
-          elsif @connections.size < @size
138  
-            checkout_new_connection
139  
-          end
140  
-        end
141  
-        return conn if conn
142  
-
143  
-        # No connections available; wait for one
144 134
         @connection_mutex.synchronize do
145  
-          if @queue.wait(@timeout)
146  
-            checkout_existing_connection
147  
-          else
148  
-            raise ConnectionTimeoutError, "could not obtain a database connection within #{@timeout} seconds.  The pool size is currently #{@size}, perhaps you need to increase it?"
  135
+          loop do
  136
+            conn = if @checked_out.size < @connections.size
  137
+                     checkout_existing_connection
  138
+                   elsif @connections.size < @size
  139
+                     checkout_new_connection
  140
+                   end
  141
+            return conn if conn
  142
+            # No connections available; wait for one
  143
+            if @queue.wait(@timeout)
  144
+              next
  145
+            else
  146
+              raise ConnectionTimeoutError, "could not obtain a database connection within #{@timeout} seconds.  The pool size is currently #{@size}, perhaps you need to increase it?"
  147
+            end
149 148
           end
150 149
         end
151 150
       end
@@ -275,4 +274,4 @@ def retrieve_connection_pool(klass)
275 274
       end
276 275
     end
277 276
   end
278  
-end
  277
+end

0 notes on commit 21eb18a

Please sign in to comment.
Something went wrong with that request. Please try again.