open-telemetry / open-telemetry/opentelemetry-ruby
Deadlock when using on_finishing to modify span object
Nobody has claimed this yet.
- Dominant language
- Ruby
- Stars
- 606
- Forks
- 301
- Avg merge
- 3d 19h
- Merged PRs (30d)
- 42
Description
Description of the bug
Calling on_finishing from processor will cause deadlock if trying to modify any object inside span.
ERROR -- : OpenTelemetry error: deadlock; recursive locking - /usr/local/bundle/gems/opentelemetry-sdk-1.8.0/lib/opentelemetry/sdk/trace/span.rb:80:in `synchronize'
This is caused by double @mutex.synchronize on finish(end_timestamp: nil) and other function such as add_attributes, etc. from processor.on_finishing(self).
Possible solutions
-
Use Monitor: since Monitor is reentrant.
-
Put the on_finishing outside the @mutex.synchronize. Since most operation on span object are within mutex.synchronize, there is no need to double synchronize.
def finish(end_timestamp: nil)
@mutex.synchronize do
if @ended
OpenTelemetry.logger.warn('Calling finish on an ended Span.')
return self
end
end
@span_processors.each do |processor|
processor.on_finishing(self) if processor.respond_to?(:on_finishing)
end
@mutex.synchronize do
@end_timestamp = relative_timestamp(end_timestamp)
@attributes = validated_attributes(@attributes).freeze
@events.freeze
@links.freeze
@ended = true
end
@span_processors.each { |processor| processor.on_finish(self) }
self
end
Share details about your runtime
Operating system details: Linux, Ubuntu 20.04 LTS
RUBY_ENGINE: "ruby"
RUBY_VERSION: "3.1.0"
RUBY_DESCRIPTION: "ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [aarch64-linux]"
Share a simplified reproduction if possible
class TestProcessor
def on_start(span, parent_context); end
def on_finishing(span)
span.set_attribute('hello', 'world')
end
def on_finish(span); end
end
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in lib/opentelemetry/sdk/trace/span.rb at finish and reproduce the deadlock with the TestProcessor example from the issue. Add a regression test showing that on_finishing can call set_attribute without recursive locking, then verify the span finishes successfully and the attribute is retained.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ruby
- Domain
- observability
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100