Skip to content

fix: prevent task GC in AsyncTeleBot by tracking background tasks#2574

Open
gilangjavier wants to merge 2 commits intoeternnoir:masterfrom
gilangjavier:fix/background-task-leak
Open

fix: prevent task GC in AsyncTeleBot by tracking background tasks#2574
gilangjavier wants to merge 2 commits intoeternnoir:masterfrom
gilangjavier:fix/background-task-leak

Conversation

@gilangjavier
Copy link

@gilangjavier gilangjavier commented Mar 18, 2026

This fix addresses the issue where was called without storing a strong reference to the task, leading to potential premature garbage collection. We now maintain a set of background tasks and add a done callback to discard them upon completion.Fixes #2572

@gilangjavier
Copy link
Author

I checked this PR and currently no CI checks are being reported on the branch (gh pr checks returns none), so status stays UNSTABLE.

Could a maintainer confirm how CI should be triggered for external contributor PRs in this repo? If there is a label/command/manual trigger needed, I can follow it.

@Badiboy Badiboy requested a review from Copilot March 19, 2026 06:02
@Badiboy
Copy link
Collaborator

Badiboy commented Mar 19, 2026

Triggered.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a potential asyncio garbage-collection issue in AsyncTeleBot polling by retaining strong references to “fire-and-forget” tasks created for update processing, aligning with Python’s asyncio.create_task() guidance.

Changes:

  • Add an instance-level _background_tasks set to retain created asyncio.Task objects.
  • Track each process_new_updates() task and discard it from the set when it completes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +457 to +459
task = asyncio.create_task(self.process_new_updates(updates))
self._background_tasks.add(task)
task.add_done_callback(self._background_tasks.discard)
Comment on lines +457 to +459
task = asyncio.create_task(self.process_new_updates(updates))
self._background_tasks.add(task)
task.add_done_callback(self._background_tasks.discard)
self.middlewares = []

self._user = None # set during polling
self._background_tasks = set()
@gilangjavier
Copy link
Author

Follow-up with exact fixes for Copilot feedback:

  • Added explicit typing for background task tracking: _background_tasks: set[asyncio.Task[Any]].
  • Replaced the discard-only callback with _on_background_task_done + _process_background_task_result so task exceptions are always retrieved and routed through _handle_exception/logger (prevents "Task exception was never retrieved").
  • Added _shutdown_background_tasks() and call it in polling finally before close_session(): wait briefly for in-flight update tasks, then cancel/drain remaining tasks before closing aiohttp session.

Commit: a01eda6

Please re-review when convenient 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Potential Bug: asyncio.create_task lacks strong references in telebot.AsyncTeleBot._process_polling

3 participants