forked from zk-ruby/zk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Modernize fork hooks to not conflict with other gems
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
Showing
1 changed file
with
43 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |