aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/connection_adapters
diff options
context:
space:
mode:
authorjeffdoering <jdoering@alum.mit.edu>2019-06-13 11:23:13 -0700
committerRafael França <rafaelmfranca@gmail.com>2019-06-13 14:23:13 -0400
commite2d11970f25890e8baa613bfa33e432bd693627b (patch)
tree775c7c1e04def3ef0371121cc2834b3f2b3ffb19 /activerecord/lib/active_record/connection_adapters
parent136f730f8d5c2625b49ffff5e319f8170aa9af1a (diff)
downloadrails-e2d11970f25890e8baa613bfa33e432bd693627b.tar.gz
rails-e2d11970f25890e8baa613bfa33e432bd693627b.tar.bz2
rails-e2d11970f25890e8baa613bfa33e432bd693627b.zip
Make ActiveRecord `ConnectionPool.connections` thread-safe. (#36473)
* Make ActiveRecord `ConnectionPool.connections` thread-safe. ConnectionPool documentation is clear on the need to synchronize access to @connections but also states that public methods do not require synchronization. Existing code exposed @connections directly via attr_reader. The fix uses synchronize() to lock @connections then returns a copy to the caller using Array.dup(). Includes comments on the connections method that thread-safe access to the connections array does not imply thread-safety of accessing methods on the actual connections. Adds a test-case that modifies the pool using a supported method in one thread while a second thread accesses pool.connections. The test fails without this patch. Fixes #36465. * Update activerecord/test/cases/connection_pool_test.rb [jeffdoering + Rafael Mendonça França]
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters')
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb17
1 files changed, 16 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
index be804325b3..adb5ae82a0 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -357,7 +357,7 @@ module ActiveRecord
include ConnectionAdapters::AbstractPool
attr_accessor :automatic_reconnect, :checkout_timeout, :schema_cache
- attr_reader :spec, :connections, :size, :reaper
+ attr_reader :spec, :size, :reaper
# Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
# object which describes database connection information (e.g. adapter,
@@ -470,6 +470,21 @@ module ActiveRecord
synchronize { @connections.any? }
end
+ # Returns an array containing the connections currently in the pool.
+ # Access to the array does not require synchronization on the pool because
+ # the array is newly created and not retained by the pool.
+ #
+ # However; this method bypasses the ConnectionPool's thread-safe connection
+ # access pattern. A returned connection may be owned by another thread,
+ # unowned, or by happen-stance owned by the calling thread.
+ #
+ # Calling methods on a connection without ownership is subject to the
+ # thread-safety guarantees of the underlying method. Many of the methods
+ # on connection adapter classes are inherently multi-thread unsafe.
+ def connections
+ synchronize { @connections.dup }
+ end
+
# Disconnects all connections in the pool, and clears the pool.
#
# Raises: