Skip to content

Commit a769866

Browse files
committed
Mark sender thread as fork safe for Puma
1 parent e5c20a3 commit a769866

2 files changed

Lines changed: 13 additions & 3 deletions

File tree

lib/datadog/statsd/sender.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def rendez_vous
5151
# could happen if #start hasn't be called
5252
return unless message_queue
5353

54-
# Initialize and get the thread's sync queue
54+
# initialize and get the thread's sync queue
5555
queue = (@thread_class.current[:statsd_sync_queue] ||= @queue_class.new)
5656
# tell sender-thread to notify us in the current
5757
# thread's queue
@@ -104,6 +104,9 @@ def start
104104
# start background thread
105105
@sender_thread = @thread_class.new(&method(:send_loop))
106106
@sender_thread.name = "Statsd Sender" unless Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.3')
107+
# advise multi-threaded app servers to ignore this thread for the purposes of fork safety warnings
108+
# see Puma's implementation for `:fork_safe`: https://github.com/puma/puma/blob/v7.2.0/lib/puma/cluster.rb#L374
109+
@sender_thread.thread_variable_set(:fork_safe, true)
107110
rescue ThreadError => e
108111
@logger.debug { "Statsd: Failed to start sender thread: #{e.message}" } if @logger
109112
@mx.synchronize { @done = true }

spec/statsd/sender_spec.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@
4848
|thds| thds.any? { |t| t.name == "Statsd Sender" }
4949
}
5050
end
51+
52+
it 'marks the sender thread as fork safe' do
53+
subject.start
54+
expect(Thread.list).to satisfy {
55+
|thds| thds.any? { |t| t.name == "Statsd Sender" && t.thread_variable_get(:fork_safe) }
56+
}
57+
end
5158
end
5259

5360
context 'when the sender is started' do
@@ -204,9 +211,9 @@
204211

205212
let(:thread_class) do
206213
if Thread.instance_methods.include?(:name=)
207-
fake_thread = instance_double(Thread, { "alive?" => true, "name=" => true, "join" => true })
214+
fake_thread = instance_double(Thread, { "alive?" => true, "name=" => true, "join" => true, "thread_variable_set" => true })
208215
else
209-
fake_thread = instance_double(Thread, { "alive?" => true, "join" => true })
216+
fake_thread = instance_double(Thread, { "alive?" => true, "join" => true, "thread_variable_set" => true })
210217
end
211218
class_double(Thread, new: fake_thread)
212219
end

0 commit comments

Comments
 (0)