Skip to content

Commit

Permalink
Use WeakRef to avoid leaking connection pools
Browse files Browse the repository at this point in the history
Prior to 3e2e8ee the Reaper thread
would hold a reference to connection pools indefinitely, preventing the
connection pool from being garbage collected, and also leaking the
Thread.

Since 3e2e8ee, there is only one Reaper
Thread for all pools, however all pools are still stored in a class
variable, preventing them from being garbage collected.

This commit instead holds reference to the pools through a WeakRef. This
way, connection pools referenced elsewhere will be reaped, any others
will be able to be garbage collected.

I don't love resorting to WeakRef to solve this, but I believe it's the
simplest way to accomplish the the desired behaviour.
  • Loading branch information
jhawthorn committed May 27, 2019
1 parent b55f5a3 commit 6302e56
Showing 1 changed file with 21 additions and 11 deletions.
Expand Up @@ -3,6 +3,7 @@
require "thread"
require "concurrent/map"
require "monitor"
require "weakref"

module ActiveRecord
# Raised when a connection could not be obtained within the connection
Expand Down Expand Up @@ -294,28 +295,37 @@ def initialize(pool, frequency)
@frequency = frequency
end

@@mutex = Mutex.new
@@pools = {}
@mutex = Mutex.new
@pools = {}

def self.register_pool(pool, frequency) # :nodoc:
@@mutex.synchronize do
if @@pools.key?(frequency)
@@pools[frequency] << pool
else
@@pools[frequency] = [pool]
class << self
def register_pool(pool, frequency) # :nodoc:
@mutex.synchronize do
unless @pools.key?(frequency)
@pools[frequency] = []
spawn_thread(frequency)
end
@pools[frequency] << WeakRef.new(pool)
end
end

private

def spawn_thread(frequency)
Thread.new(frequency) do |t|
loop do
sleep t
@@mutex.synchronize do
@@pools[frequency].each do |p|
@mutex.synchronize do
@pools[frequency].select!(&:weakref_alive?)
@pools[frequency].each do |p|
p.reap
p.flush
rescue WeakRef::RefError
end
end
end
end
end
end
end

def run
Expand Down

0 comments on commit 6302e56

Please sign in to comment.