Module: Datadog::Profiling::Ext::Forking::Kernel

Defined in:
lib/datadog/profiling/ext/forking.rb

Overview

Extensions for kernel

TODO: Consider hooking into ‘Process._fork` on Ruby 3.1+ instead, see

https://github.com/ruby/ruby/pull/5017 and https://bugs.ruby-lang.org/issues/17795

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.ddtrace_at_fork_blocksObject



69
70
71
72
73
74
75
# File 'lib/datadog/profiling/ext/forking.rb', line 69

def ddtrace_at_fork_blocks
  # Blocks should be shared across all users of this module,
  # e.g. Process#fork, Kernel#fork, etc. should all invoke the same callbacks.
  # rubocop:disable Style/ClassVars
  @@ddtrace_at_fork_blocks ||= {}
  # rubocop:enable Style/ClassVars
end

Instance Method Details

#at_fork(stage, &block) ⇒ Object

Raises:

  • (ArgumentError)


60
61
62
63
64
65
# File 'lib/datadog/profiling/ext/forking.rb', line 60

def at_fork(stage, &block)
  raise ArgumentError, 'Bad \'stage\' for ::at_fork' unless stage == :child

  ddtrace_at_fork_blocks[stage] = [] unless ddtrace_at_fork_blocks.key?(stage)
  ddtrace_at_fork_blocks[stage] << block
end

#forkObject



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/datadog/profiling/ext/forking.rb', line 35

def fork
  # If a block is provided, it must be wrapped to trigger callbacks.
  child_block = if block_given?
                  proc do
                    # Trigger :child callback
                    ddtrace_at_fork_blocks[:child].each(&:call) if ddtrace_at_fork_blocks.key?(:child)

                    # Invoke original block
                    yield
                  end
                end

  # Start fork
  # If a block is provided, use the wrapped version.
  result = child_block.nil? ? super : super(&child_block)

  # Trigger correct callbacks depending on whether we're in the parent or child.
  # If we're in the fork, result = nil: trigger child callbacks.
  # If we're in the parent, result = fork PID: trigger parent callbacks.
  ddtrace_at_fork_blocks[:child].each(&:call) if result.nil? && ddtrace_at_fork_blocks.key?(:child)

  # Return PID from #fork
  result
end