1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/activesupport/lib/active_support/fork_tracker.rb
Petrik 332a2909d4 Fix ForkTracker on ruby <= 2.5.3
Making the fork method private by calling `private :fork` raises a
"no superclass method `fork'" error when calling super in a subclass on
ruby <= 2.5.3. The error doesn't occur on ruby 2.5.4 and higher.
Making the method private by redefining doesn't raise the error.

The possible fix on 2.5.4 is 75aba10d7a

The error can be reproduced with the following script on ruby 2.5.3:
```
class Cluster
  def start
    fork { puts "forked!" }
  end
end

module CoreExt
  def fork(*)
    super
  end
end

module CoreExtPrivate
  include CoreExt
  private :fork
end

::Object.prepend(CoreExtPrivate)
Cluster.new.start
```

Fixes #40603
2020-11-17 21:22:12 +01:00

62 lines
1.1 KiB
Ruby

# frozen_string_literal: true
module ActiveSupport
module ForkTracker # :nodoc:
module CoreExt
def fork(*)
if block_given?
super do
ForkTracker.check!
yield
end
else
unless pid = super
ForkTracker.check!
end
pid
end
end
end
module CoreExtPrivate
include CoreExt
private
def fork(*)
super
end
end
@pid = Process.pid
@callbacks = []
class << self
def check!
if @pid != Process.pid
@callbacks.each(&:call)
@pid = Process.pid
end
end
def hook!
if Process.respond_to?(:fork)
::Object.prepend(CoreExtPrivate)
::Kernel.prepend(CoreExtPrivate)
::Kernel.singleton_class.prepend(CoreExt)
::Process.singleton_class.prepend(CoreExt)
end
end
def after_fork(&block)
@callbacks << block
block
end
def unregister(callback)
@callbacks.delete(callback)
end
end
end
end
ActiveSupport::ForkTracker.hook!