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

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

Overview

Extensions for kernel

Constant Summary collapse

FORK_STAGES =
[:prepare, :parent, :child].freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.at_fork_blocksObject



87
88
89
90
91
92
93
# File 'lib/ddtrace/profiling/ext/forking.rb', line 87

def 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
  @@at_fork_blocks ||= {}
  # rubocop:enable Style/ClassVars
end

Instance Method Details

#at_fork(stage = :prepare, &block) ⇒ Object

Raises:

  • (ArgumentError)


78
79
80
81
82
83
# File 'lib/ddtrace/profiling/ext/forking.rb', line 78

def at_fork(stage = :prepare, &block)
  raise ArgumentError, 'Bad \'stage\' for ::at_fork' unless FORK_STAGES.include?(stage)

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

#forkObject



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/ddtrace/profiling/ext/forking.rb', line 42

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

                    # Invoke original block
                    yield
                  end
                end

  # Trigger :prepare callback
  at_fork_blocks[:prepare].each(&:call) if at_fork_blocks.key?(:prepare)

  # 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.
  # rubocop:disable Style/IfInsideElse
  if result.nil?
    # Trigger :child callback
    at_fork_blocks[:child].each(&:call) if at_fork_blocks.key?(:child)
  else
    # Trigger :parent callback
    at_fork_blocks[:parent].each(&:call) if at_fork_blocks.key?(:parent)
  end
  # rubocop:enable Style/IfInsideElse

  # Return PID from #fork
  result
end