Skip to content

Commit

Permalink
Modernize fork hooks to not conflict with other gems
Browse files Browse the repository at this point in the history
Fix: zk-ruby#108

`Module#prepend` is much more composable than alias method chains.

This is essentially a port of the Active Support implementation.
  • Loading branch information
byroot committed Jun 20, 2023
1 parent 5169d1b commit a0a16c9
Showing 1 changed file with 43 additions and 29 deletions.
72 changes: 43 additions & 29 deletions lib/zk/install_fork_hooks.rb
Original file line number Diff line number Diff line change
@@ -1,37 +1,51 @@
module ::Kernel
def fork_with_zk_hooks(&block)
if block
new_block = proc do
::ZK::ForkHook.fire_after_child_hooks!
block.call
module ZK
module ForkHook
module ModernCoreExt
def _fork
::ZK::ForkHook.fire_prepare_hooks!
pid = super
if pid == 0
::ZK::ForkHook.fire_after_child_hooks!
else
::ZK::ForkHook.fire_after_parent_hooks!
end
pid
end
end

::ZK::ForkHook.fire_prepare_hooks!
fork_without_zk_hooks(&new_block).tap do
::ZK::ForkHook.fire_after_parent_hooks!
end
else
::ZK::ForkHook.fire_prepare_hooks!
if pid = fork_without_zk_hooks
::ZK::ForkHook.fire_after_parent_hooks!
# we're in the parent
return pid
else
# we're in the child
::ZK::ForkHook.fire_after_child_hooks!
return nil
module CoreExt
def fork(*, **)
::ZK::ForkHook.fire_prepare_hooks!
if block_given?
pid = super do
::ZK::ForkHook.fire_after_child_hooks!
yield
end
::ZK::ForkHook.fire_after_parent_hooks!
else
if pid = super
ZK::ForkHook.fire_after_parent_hooks!
else
::ZK::ForkHook.fire_after_child_hooks!
end
end

pid
end
end
end

if defined?(fork_without_zk_hooks)
remove_method :fork
alias fork fork_without_zk_hooks
remove_method :fork_without_zk_hooks
module CoreExtPrivate
include CoreExt
private :fork
end
end

alias fork_without_zk_hooks fork
alias fork fork_with_zk_hooks
module_function :fork
end

if Process.respond_to?(:_fork) # Ruby 3.1+
::Process.singleton_class.prepend(ZK::ForkHook::ModernCoreExt)
elsif Process.respond_to?(:fork)
::Object.prepend(ZK::ForkHook::CoreExtPrivate) if RUBY_VERSION < "3.0"
::Kernel.prepend(ZK::ForkHook::CoreExtPrivate)
::Kernel.singleton_class.prepend(ZK::ForkHook::CoreExt)
::Process.singleton_class.prepend(ZK::ForkHook::CoreExt)
end

0 comments on commit a0a16c9

Please sign in to comment.