From: "ivoanjo (Ivo Anjo)" Date: 2022-07-14T08:12:01+00:00 Subject: [ruby-core:109204] [Ruby master Bug#18911] Process._fork hook point is not called when Process.daemon is used Issue #18911 has been updated by ivoanjo (Ivo Anjo). Thanks @mame for the awesomely quick reply :) > @ivoanjo (Ivo Anjo) Do you have difficulties due to this behavior in terms of ddtrace? Or you were just "surprised"? The motivation is very important to discuss the issue. Process.daemon stops threads, so I guess you have any difficulties, but I'd like to confirm it before the dev meeting. Yeah, it surprised me because it was a situation where there's a fork (albeit indirectly) and threads die, so I needed to do cleanups/restart stuff, but was not covered by the `_fork`. > @nobu (Nobuyoshi Nakada) said that this is because Process.daemon does not call fork(2) but daemon(3). We happen to know that daemon(3) calls fork(2) (on some environments), but other unknown C functions calling fork internally cannot be handled. So Process._fork hooks only events that Ruby calls fork(2) directly. I guess this is perhaps more of a discoverability/documentation issue. My understanding was "hooking `_fork` was all you needed", but actually daemon needs to be as well. But in practical terms, if I'm hooking `Process._fork`, it's not hard to also hook `Process.daemon`. Next to the code implementing `_fork` we have the following comment: ```c /* ... * This method is not for casual code but for application monitoring * libraries. You can add custom code before and after fork events * by overriding this method. */ VALUE rb_proc__fork(VALUE _obj) ``` ...would it be reasonable to add a "Note: Process#daemon is similar to fork, but does not go through this method." or something similar? ---------------------------------------- Bug #18911: Process._fork hook point is not called when Process.daemon is used https://bugs.ruby-lang.org/issues/18911#change-98342 * Author: ivoanjo (Ivo Anjo) * Status: Open * Priority: Normal * Assignee: akr (Akira Tanaka) * ruby -v: ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin20] * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN ---------------------------------------- Hello there! I'm working at Datadog [on the `ddtrace` gem](https://github.com/DataDog/dd-trace-rb), and we need to hook into fork operations to make sure that our products work correctly/automatically even in environments that fork. As part as #17795 a new `Process._fork` method was added to allow libraries and frameworks to easily hook into fork operations. I was investigating its use in `ddtrace` and noticed the following gap: the `Process.daemon` API internally makes use of `fork`, but the new hook point is not called for that API. Testcase: ```ruby puts RUBY_DESCRIPTION module ForkHook def _fork(*args) puts " #{Process.pid} Before fork!" res = super puts " #{Process.pid} After fork!" res end end Process.singleton_class.prepend(ForkHook) puts "#{Process.pid} Regular fork:" fork { exit } Process.wait puts "#{Process.pid} Process.daemon:" Process.daemon(nil, true) puts "#{Process.pid} Finishing!" ``` Testcase output: ``` ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin20] 48136 Regular fork: # <-- original process 48136 Before fork! 48136 After fork! # <-- original process 48137 After fork! # <-- child process 48136 Process.daemon: # <-- original process 48139 Finishing! # <-- forks and pid changes, but the hook isn't called ``` This was surprising to me since the advantage of this hook point would not not needing to hook into the many other places where `fork` can get called from. Thanks a lot :) -- https://bugs.ruby-lang.org/ Unsubscribe: