Skip to content

Commit

Permalink
Working ConnectionPool disconnect! on fork callbacks.
Browse files Browse the repository at this point in the history
  • Loading branch information
kstephens committed Feb 8, 2011
1 parent 0ae0f06 commit ad5b682
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 1 deletion.
35 changes: 34 additions & 1 deletion README.rdoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,39 @@
= rails_is_forked

Description goes here.
Rails does not clear ConnectionPool in Process.fork children:

puts "Parent #{$$}: #{ActiveRecord::Base.connection.object_id}"
fork { puts "Child: #{$$}: #{ActiveRecord::Base.connection.object_id}" }
Thread.new { puts "Thread: #{ActiveRecord::Base.connection.object_id}" }

Sample Output:

Parent 27282: 153210860
Child: 29777: 153210860
Thread: 153076390

Note that Threads get their own connections, but subprocesses do not.

A ConnectionPool exists for each ActiveRecord::Base subclass that has been sent :establish_connection.

puts "Parent #{$$}: #{ActiveRecord::Base.connection_pool.object_id}"
fork { puts "Child: #{$$}: #{ActiveRecord::Base.connection_pool.object_id}" }
Thread.new { puts "Thread: #{ActiveRecord::Base.connection_pool.object_id}" }

Sample Output:

Parent 30003: 102371950
Child: 30053: 102371950
Thread: 102371950

Note that ConnectionPools are only uniq per process.

This gem adds:

* RailsIsForked::ForkCallback:
** Callbacks in children (and parents) of Process.fork (and Kernel.fork). This is useful for non-Rails apps.
* RailsIsForked::Rails:
** Calls ActiveRecord::ConnectionAdapters::ConnectionPool#disconnect! for all instances in forked children. See ActiveRecord::Base.connection_handler.connection_pools.

== Contributing to rails_is_forked

Expand Down
16 changes: 16 additions & 0 deletions cabar.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
cabar:
version: v1.0

component:
version: v1.0
description: 'rails_is_forked - Create new DB connections in forked children.'

provides:
bin: true
lib/ruby: lib
cnu_config_path: true
tests: spec

requires:
component:
ruby: true
28 changes: 28 additions & 0 deletions lib/rails_is_forked/rails.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require 'rails_is_forked/fork_callback'

require 'active_record/connection_adapters/abstract/connection_pool'

module RailsIsForked
module ConnectionPoolDisconnectOnFork
@@once = false

def self.included target
super

return if @@once
@@once = true

# Register callback to call ConnectionPool#disconnect! on all instances.
proc = RailsIsForked::ForkCallback.add_callback_in_child! do | child_pid |
ActiveRecord::Base.connection_handler.connection_pools.each_value do | pool |
# $stderr.puts "#{$$}: #{pool}.disconnect!"
pool.disconnect!
end
end
# $stderr.puts "Registered callback #{proc}"
end

::ActiveRecord::ConnectionAdapters::ConnectionPool.send(:include, self)
end
end

0 comments on commit ad5b682

Please sign in to comment.