Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: resolve asyncio event loop bug when gevent is installed [backpor…
…t 2.19] (#11921) Backport b769e1e from #11904 to 2.19. ## Description Reverts a change ([4e31278](4e31278)) that introduced a regression in asyncio event loops when gevent is installed. This issue cannot be reproduced on macOS; it was detected on Ubuntu 24. ## Background - In ddtrace v2.11.0, the ddtrace-py [introduced support](dc000ae) for crash tracking, and the crash tracker is started via ddtrace-run or by importing ddtrace.auto ([here](https://github.com/DataDog/dd-trace-py/blob/main/ddtrace/auto.py)). - Before the crash tracker is started, it [reads the agent URL](https://github.com/DataDog/dd-trace-py/blob/v2.11.0/ddtrace/internal/core/crashtracking.py#L31) using the [ensure_binary](https://github.com/DataDog/dd-trace-py/blob/a58f139e24d78a66468dbc7f67ec42c2bdfad8ee/ddtrace/internal/datadog/profiling/crashtracker/_crashtracker.pyx#L50) function. - The ensure_binary function imports unittest.mock, which imports [asyncio](https://github.com/DataDog/dd-trace-py/blob/v2.11.0/ddtrace/internal/compat.py#L72) as a side effect. - After crash tracking is started, ddtrace unloads all modules that were imported during the setup of ddtrace features ([here](https://github.com/DataDog/dd-trace-py/blob/main/ddtrace/bootstrap/sitecustomize.py#L120C5-L120C27)). This includes asyncio. - At this point, asyncio has been added to and then removed from sys.modules. - When asyncio is imported in a user's application event loops fail to be set. This is seen in the script below (the script was run on Ubuntu 24 with gevent>=24) ### Script ``` import asyncio import time loop = asyncio.get_event_loop() loop_id = id(loop) new_loop = asyncio.new_event_loop() new_loop_id = id(new_loop) print(f"old: {loop_id} new: {new_loop_id}") asyncio.set_event_loop(new_loop) check = asyncio.get_event_loop() check_id = id(check) print(f"check: {id(check)}") while check_id != new_loop_id: print("MISMATCH") print(f"check: {id(check)}") time.sleep(1) check = asyncio.get_event_loop() check_id = id(check) ``` ### Output ``` MISMATCH check: 131621237174144 MISMATCH check: 131621237174144 MISMATCH check: 131621237174144 MISMATCH check: 131621237174144 MISMATCH check: 131621237174144 MISMATCH ``` ## Next steps Investigate module unloading and asyncio incompatibility ## 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 - [x] 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) Co-authored-by: Munir Abdinur <munir.abdinur@datadoghq.com>
- Loading branch information