require 'bundler/setup'
require 'eppo_client'
config = EppoClient::Config.new(
'test-api-key-12345',
log_level: 'warn',
poll_interval_seconds: 300
)
EppoClient::init(config)
client = EppoClient::Client.instance
client.wait_for_initialization(1)
pid = Process.fork do
puts " [Child] Forked successfully"
sleep 0.1
exit 0
end
Process.wait(pid)
Output:
1. Initializing Eppo client...
2. Waiting for client initialization...
[2025-12-18T16:40:18Z WARN eppo] client is not authorized. Check your API key
Client initialized successfully
3. Forking process...
[Child] Forked successfully
thread '<unnamed>' (4148640) panicked at /Users/danny/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.44.1/src/runtime/io/driver.rs:208:27:
failed to wake I/O driver: Os { code: 9, kind: Uncategorized, message: "Bad file descriptor" }
stack backtrace:
0: 0x1218af30c - <std::sys::backtrace::BacktraceLock::print::DisplayBacktrace as core::fmt::Display>::fmt::hace9c8f0bf02b28d
1: 0x1218c3988 - core::fmt::write::haff06c4d5dadd744
2: 0x1218a453c - std::io::default_write_fmt::h349b76ae705bfbb3
3: 0x1218ac634 - std::io::Write::write_fmt::h5ddde028a424c999
4: 0x1218ae190 - std::sys::backtrace::BacktraceLock::print::hd758fb250dfaa015
5: 0x1218a1d00 - std::panicking::default_hook::{{closure}}::hf0b2effb73fcdb33
6: 0x1218a1c18 - std::panicking::default_hook::h91163188c82e55a1
7: 0x1218a1fc4 - std::panicking::panic_with_hook::h9d9f4b295fd289e2
8: 0x1218ae51c - std::panicking::panic_handler::{{closure}}::h3b0d19ced6899bb8
9: 0x1218ae29c - std::sys::backtrace::__rust_end_short_backtrace::h2bd50c9fdd80557b
10: 0x1218a0ba8 - __rustc[834c5bfdc4cd1ec3]::rust_begin_unwind
11: 0x1218e075c - core::panicking::panic_fmt::h49b99017a75b3cd4
12: 0x1218e03b4 - core::result::unwrap_failed::h4df382aa3f2dc484
13: 0x121870358 - <tokio::runtime::scheduler::current_thread::Handle as tokio::util::wake::Wake>::wake::hf642571f9fdd8a6b
14: 0x1218795c8 - tokio::sync::notify::Notify::notify_waiters::h3f5f579a2f14e82c
15: 0x1215ea57c - core::ptr::drop_in_place<eppo_core::background::runtime::BackgroundRuntime<tokio::runtime::handle::Handle>>::hafd8a998d77216b2
16: 0x1215ed874 - magnus::typed_data::DataTypeFunctions::extern_free::hb982338b837a4672
17: 0x10158e20c - _finalize_deferred_heap_pages
18: 0x101586014 - _rb_objspace_call_finalizer
19: 0x1015740f0 - _rb_ec_cleanup
20: 0x10157420c - _ruby_stop
21: 0x101639f48 - _rb_f_fork
22: 0x10172348c - _vm_call_cfunc_with_frame_
23: 0x101707948 - _vm_exec_core
24: 0x101705474 - _rb_vm_exec
25: 0x1015d68ac - _load_iseq_eval
26: 0x1015d3c1c - _rb_load_internal
27: 0x1015d57fc - _rb_f_load
28: 0x10172348c - _vm_call_cfunc_with_frame_
29: 0x101709ab4 - _vm_exec_core
30: 0x101705630 - _rb_vm_exec
31: 0x1015d68ac - _load_iseq_eval
32: 0x1015d3c1c - _rb_load_internal
33: 0x1015d57fc - _rb_f_load
34: 0x10172348c - _vm_call_cfunc_with_frame_
35: 0x101709ab4 - _vm_exec_core
36: 0x101705474 - _rb_vm_exec
37: 0x101574394 - _rb_ec_exec_node
38: 0x1015742bc - _ruby_run_node
39: 0x100c9c5d8 - _main
reproduce_panic.rb:14: [BUG] failed to wake I/O driver: Os { code: 9, kind: Uncategorized, message: "Bad file descriptor" }
ruby 3.4.7 (2025-10-08 revision 7a5688e2a2) +PRISM [arm64-darwin25]
This is the most trivial way to reproduce what I consider to be something the SDK should handle without blowing up - have you considered pthread_atfork to shut down Eppo in the event of a fork, or otherwise gracefully handle being forked without crashing Ruby?
Output:
This is the most trivial way to reproduce what I consider to be something the SDK should handle without blowing up - have you considered
pthread_atforkto shut down Eppo in the event of a fork, or otherwise gracefully handle being forked without crashing Ruby?