mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
332a2909d4
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
62 lines
1.1 KiB
Ruby
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!
|