From 8415749f8bb3ba3cfd8fab9660f54a250fbbb2e1 Mon Sep 17 00:00:00 2001 From: "Gabriele N. Tornetta" Date: Thu, 18 Sep 2025 11:54:11 +0100 Subject: [PATCH] fix(di): get pending probes as a copy (#14608) When retrieving the list of pending probes, we make the registry return a copy of the collection to avoid mutation during iteration. In the worst case, Python does not warn that the list has been mutated while iterating over it, causing the iteration loop to end prematurely without any sings of errors. ## Checklist - [x] PR author has checked that all the criteria below are met - The PR description includes an overview of the change - The PR description articulates the motivation for the change - The change includes tests OR the PR description describes a testing strategy - The PR description notes risks associated with the change, if any - Newly-added code is easy to change - The change follows the [library release note guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html) - The change includes or references documentation updates if necessary - Backport labels are set (if [applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)) ## Reviewer Checklist - [ ] Reviewer has checked that all the criteria below are met - Title is accurate - All changes are related to the pull request's stated goal - Avoids breaking [API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces) changes - Testing strategy adequately addresses listed risks - Newly-added code is easy to change - Release note makes sense to a user of the library - If necessary, 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) (cherry picked from commit 67da5b52f93faaa37bfcf15ab51c6ddbfc721779) --- ddtrace/debugging/_probe/registry.py | 2 +- .../notes/fix-di-copy-pending-probes-be21850231275165.yaml | 5 +++++ tests/debugging/test_debugger.py | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/fix-di-copy-pending-probes-be21850231275165.yaml diff --git a/ddtrace/debugging/_probe/registry.py b/ddtrace/debugging/_probe/registry.py index 83a56ad40f9..e1a578794b4 100644 --- a/ddtrace/debugging/_probe/registry.py +++ b/ddtrace/debugging/_probe/registry.py @@ -203,7 +203,7 @@ def unregister(self, *probes: Probe) -> List[Probe]: def get_pending(self, location: str) -> List[Probe]: """Get the currently pending probes by location.""" - return self._pending[location] + return self._pending[location].copy() def __contains__(self, probe: object) -> bool: """Check if a probe is in the registry.""" diff --git a/releasenotes/notes/fix-di-copy-pending-probes-be21850231275165.yaml b/releasenotes/notes/fix-di-copy-pending-probes-be21850231275165.yaml new file mode 100644 index 00000000000..8d2ee95d202 --- /dev/null +++ b/releasenotes/notes/fix-di-copy-pending-probes-be21850231275165.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + dynamic instrumentation: fix an issue that prevented multiple probes on the + same location from being instrumented. diff --git a/tests/debugging/test_debugger.py b/tests/debugging/test_debugger.py index 0e9ad67698d..54335f7a972 100644 --- a/tests/debugging/test_debugger.py +++ b/tests/debugging/test_debugger.py @@ -553,6 +553,8 @@ def test_debugger_multiple_function_probes_on_same_lazy_module(): for i in range(3) ] + sys.modules.pop("tests.submod.stuff", None) + with debugger() as d: d.add_probes(*probes) @@ -560,6 +562,7 @@ def test_debugger_multiple_function_probes_on_same_lazy_module(): assert len(d._probe_registry) == len(probes) assert all(_.error_type is None for _ in d._probe_registry.values()) + assert len(d._probe_registry._pending) == 0 # DEV: The following tests are to ensure compatibility with the tracer