Skip to content

Commit ba6c259

Browse files
MirrorDNA-Reflection-ProtocolmdrxyCopilot
authored
fix(core): prevent async task garbage collection (RUF006) (#34238)
# PR Title: fix(core): prevent async task garbage collection (RUF006) ## Description This PR addresses a cryptic issue (flagged by Ruff rule RUF006) where `asyncio` tasks created via `loop.create_task` could be garbage collected mid-execution because no strong reference was maintained. In `libs/core/langchain_core/language_models/llms.py`, the retry decorator's `_before_sleep` hook creates a fire-and-forget task for logging/callbacks. If the garbage collector runs before this task completes, the task may be destroyed, leading to silent failures. ## Changes - Introduced a module-level set `_background_tasks` to hold strong references to running tasks. - Updated `_before_sleep` to add new tasks to this set. - Added a `done_callback` to remove the task from the set upon completion, preventing memory leaks. ## Verification - Verified logic with a standalone script to ensure tasks are added/removed from the set correctly. - This is a standard pattern recommended in the Python `asyncio` documentation. ## Checklist - [x] I have read the contributing guidelines. - [x] I have run tests locally (logic verification). --------- Co-authored-by: Mason Daugherty <[email protected]> Co-authored-by: Mason Daugherty <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent bb71f53 commit ba6c259

File tree

1 file changed

+5
-3
lines changed
  • libs/core/langchain_core/language_models

1 file changed

+5
-3
lines changed

libs/core/langchain_core/language_models/llms.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161

6262
logger = logging.getLogger(__name__)
6363

64+
_background_tasks: set[asyncio.Task] = set()
65+
6466

6567
@functools.lru_cache
6668
def _log_error_once(msg: str) -> None:
@@ -100,9 +102,9 @@ def _before_sleep(retry_state: RetryCallState) -> None:
100102
asyncio.run(coro)
101103
else:
102104
if loop.is_running():
103-
# TODO: Fix RUF006 - this task should have a reference
104-
# and be awaited somewhere
105-
loop.create_task(coro) # noqa: RUF006
105+
task = loop.create_task(coro)
106+
_background_tasks.add(task)
107+
task.add_done_callback(_background_tasks.discard)
106108
else:
107109
asyncio.run(coro)
108110
except Exception as e:

0 commit comments

Comments
 (0)