Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the tracer thread-safe #74

Merged
merged 1 commit into from
Aug 13, 2024

Conversation

pocke
Copy link
Contributor

@pocke pocke commented Aug 1, 2024

Problem

This gem raises DiverDown::Trace::CallStack::StackEmptyError while investigating a Rails application.

I assumed the cause is thread-unsafe code, and I made a small code to reproduce it.
This code raises the StackEmptyError (it is not 100% occurred as with most thread-unsafe problems).

require 'diver_down-trace'

class M
  def f
    N.new.g
  end
end

class N
  def g
  end
end

defn = DiverDown::Trace::Tracer.new(module_set: { modules: [M] }).trace do
  10.times.map do
    Thread.new { 10_000.times { M.new.f } }
  end.each(&:join)
end

pp defn.to_h
$ ruby -Ilib/ tmp/test.rb
#<Thread:0x000000011ff92f48 tmp/test.rb:16 run> terminated with exception (report_on_exception is true):
/Users/kuwabara.masataka/ghq/github.com/alpaca-tc/diver_down/lib/diver_down/trace/call_stack.rb:52:in 'DiverDown::Trace::CallStack#pop': DiverDown::Trace::CallStack::StackEmptyError (DiverDown::Trace::CallStack::StackEmptyError)
        from /Users/kuwabara.masataka/ghq/github.com/alpaca-tc/diver_down/lib/diver_down/trace/session.rb:52:in 'block in DiverDown::Trace::Session#build_trace_point'
        from tmp/test.rb:16:in 'block (3 levels) in <main>'
/Users/kuwabara.masataka/ghq/github.com/alpaca-tc/diver_down/lib/diver_down/trace/call_stack.rb:52:in 'DiverDown::Trace::CallStack#pop': DiverDown::Trace::CallStack::StackEmptyError (DiverDown::Trace::CallStack::StackEmptyError)
        from /Users/kuwabara.masataka/ghq/github.com/alpaca-tc/diver_down/lib/diver_down/trace/session.rb:52:in 'block in DiverDown::Trace::Session#build_trace_point'
        from tmp/test.rb:16:in 'block (3 levels) in <main>'

Solution

This is because several threads update the same DiverDown::Trace::CallStack object.
So I separated the call stack object for each thread.

@alpaca-tc alpaca-tc merged commit bb85b95 into alpaca-tc:main Aug 13, 2024
6 checks passed
@alpaca-tc
Copy link
Owner

Thank you for the great PR!

@pocke pocke deleted the Make_the_tracer_thread_safe branch August 14, 2024 01:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants