Skip to content

Commit

Permalink
chore(di): fix infinite loop in exception replay (#9317)
Browse files Browse the repository at this point in the history
The change that added third-party code detection to exception replay
introduced a potential infinite loop. We change the coding to avoid that
scenario.

## Checklist

- [x] Change(s) are motivated and described in the PR description
- [x] Testing strategy is described if automated tests are not included
in the PR
- [x] Risks are described (performance impact, potential for breakage,
maintainability)
- [x] Change is maintainable (easy to change, telemetry, documentation)
- [x] [Library release note
guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html)
are followed or label `changelog/no-changelog` is set
- [x] Documentation is included (in-code, generated user docs, [public
corp docs](https://github.com/DataDog/documentation/))
- [x] Backport labels are set (if
[applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting))
- [x] If this PR changes the public interface, I've notified
`@DataDog/apm-tees`.

## Reviewer Checklist

- [ ] Title is accurate
- [ ] All changes are related to the pull request's stated goal
- [ ] Description motivates each change
- [ ] Avoids breaking
[API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces)
changes
- [ ] Testing strategy adequately addresses listed risks
- [ ] Change is maintainable (easy to change, telemetry, documentation)
- [ ] Release note makes sense to a user of the library
- [ ] Author has acknowledged and discussed the performance implications
of this PR as reported in the benchmarks PR comment
- [ ] Backport labels are set in a manner that is consistent with the
[release branch maintenance
policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)
  • Loading branch information
P403n1x87 authored May 20, 2024
1 parent f6ab597 commit c045d04
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 28 deletions.
54 changes: 26 additions & 28 deletions ddtrace/debugging/_exception/auto_instrument.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,34 +178,32 @@ def on_span_finish(self, span: Span) -> None:
code = frame.f_code
seq_nr = next(seq)

if not is_user_code(Path(frame.f_code.co_filename)):
continue

snapshot_id = frame.f_locals.get(SNAPSHOT_KEY, None)
if snapshot_id is None:
# We don't have a snapshot for the frame so we create one
snapshot = SpanExceptionSnapshot(
probe=SpanExceptionProbe.build(exc_id, frame),
frame=frame,
thread=current_thread(),
trace_context=span,
exc_id=exc_id,
)

# Capture
snapshot.line()

# Collect
self.collector.push(snapshot)

# Memoize
frame.f_locals[SNAPSHOT_KEY] = snapshot_id = snapshot.uuid

# Add correlation tags on the span
span.set_tag_str(FRAME_SNAPSHOT_ID_TAG % seq_nr, snapshot_id)
span.set_tag_str(FRAME_FUNCTION_TAG % seq_nr, code.co_name)
span.set_tag_str(FRAME_FILE_TAG % seq_nr, code.co_filename)
span.set_tag_str(FRAME_LINE_TAG % seq_nr, str(_tb.tb_lineno))
if is_user_code(Path(frame.f_code.co_filename)):
snapshot_id = frame.f_locals.get(SNAPSHOT_KEY, None)
if snapshot_id is None:
# We don't have a snapshot for the frame so we create one
snapshot = SpanExceptionSnapshot(
probe=SpanExceptionProbe.build(exc_id, frame),
frame=frame,
thread=current_thread(),
trace_context=span,
exc_id=exc_id,
)

# Capture
snapshot.line()

# Collect
self.collector.push(snapshot)

# Memoize
frame.f_locals[SNAPSHOT_KEY] = snapshot_id = snapshot.uuid

# Add correlation tags on the span
span.set_tag_str(FRAME_SNAPSHOT_ID_TAG % seq_nr, snapshot_id)
span.set_tag_str(FRAME_FUNCTION_TAG % seq_nr, code.co_name)
span.set_tag_str(FRAME_FILE_TAG % seq_nr, code.co_filename)
span.set_tag_str(FRAME_LINE_TAG % seq_nr, str(_tb.tb_lineno))

# Move up the stack
_tb = _tb.tb_next
Expand Down
3 changes: 3 additions & 0 deletions tests/debugging/exception/test_auto_instrument.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import ddtrace
import ddtrace.debugging._exception.auto_instrument as auto_instrument
from ddtrace.internal.packages import _third_party_packages
from ddtrace.internal.rate_limiter import BudgetRateLimiterWithJitter as RateLimiter
from tests.debugging.mocking import exception_debugging
from tests.utils import TracerTestCase
Expand All @@ -24,8 +25,10 @@ def setUp(self):
super(ExceptionDebuggingTestCase, self).setUp()
self.backup_tracer = ddtrace.tracer
ddtrace.tracer = self.tracer
_third_party_packages().remove("ddtrace")

def tearDown(self):
_third_party_packages().add("ddtrace")
ddtrace.tracer = self.backup_tracer
super(ExceptionDebuggingTestCase, self).tearDown()

Expand Down

0 comments on commit c045d04

Please sign in to comment.