fix: store asyncio task references to prevent GC mid-execution (#3267)

Python's asyncio event loop holds only weak references to tasks.
Without a strong reference, the garbage collector can destroy a task
while it's awaiting I/O — silently dropping messages. Python 3.12+
made this more aggressive.

Audit of all gateway platform adapters found 6 untracked create_task
calls across 6 files:

Per-message tasks (tracked via _background_tasks set from base class):
- gateway/platforms/webhook.py: handle_message task
- gateway/platforms/sms.py: handle_message task
- gateway/platforms/signal.py: SSE response aclose task

Long-running infrastructure tasks (stored in named instance vars):
- gateway/platforms/slack.py: Socket Mode handler (_socket_mode_task)
- gateway/platforms/discord.py: bot client (_bot_task)
- gateway/platforms/whatsapp.py: message poll loop (_poll_task, 2 sites)

All other adapters (telegram, mattermost, matrix, email, homeassistant,
dingtalk) already tracked their tasks correctly.

Salvaged from PR #3160 by memosr — expanded from 1 file to 6.
This commit is contained in:
Teknium
2026-03-26 14:36:24 -07:00
committed by GitHub
parent 3a86328847
commit 243ee67529
6 changed files with 16 additions and 7 deletions

View File

@@ -363,7 +363,9 @@ class WebhookAdapter(BasePlatformAdapter):
)
# Non-blocking — return 202 Accepted immediately
asyncio.create_task(self.handle_message(event))
task = asyncio.create_task(self.handle_message(event))
self._background_tasks.add(task)
task.add_done_callback(self._background_tasks.discard)
return web.json_response(
{