Skip to content

Commit

Permalink
Hold references to background tasks to avoid garbage collection
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrinberg committed Jan 6, 2024
1 parent 88b19f9 commit 0729554
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 2 deletions.
15 changes: 13 additions & 2 deletions src/engineio/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@

async_signal_handler_set = False

# this set is used to keep references to background tasks to prevent them from
# being garbage collected mid-execution. Solution taken from
# https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task
task_reference_holder = set()


def async_signal_handler():
"""SIGINT handler.
Expand Down Expand Up @@ -450,8 +455,11 @@ async def _trigger_event(self, event, *args, **kwargs):
if event in self.handlers:
if asyncio.iscoroutinefunction(self.handlers[event]) is True:
if run_async:
return self.start_background_task(self.handlers[event],
task = self.start_background_task(self.handlers[event],
*args)
task_reference_holder.add(task)
task.add_done_callback(task_reference_holder.discard)
return task
else:
try:
ret = await self.handlers[event](*args)
Expand All @@ -468,7 +476,10 @@ async def _trigger_event(self, event, *args, **kwargs):
async def async_handler():
return self.handlers[event](*args)

return self.start_background_task(async_handler)
task = self.start_background_task(async_handler)
task_reference_holder.add(task)
task.add_done_callback(task_reference_holder.discard)
return task
else:
try:
ret = self.handlers[event](*args)
Expand Down
9 changes: 9 additions & 0 deletions src/engineio/async_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
from . import packet
from . import async_socket

# this set is used to keep references to background tasks to prevent them from
# being garbage collected mid-execution. Solution taken from
# https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task
task_reference_holder = set()


class AsyncServer(base_server.BaseServer):
"""An Engine.IO server for asyncio.
Expand Down Expand Up @@ -487,6 +492,8 @@ async def run_async_handler():

if run_async:
ret = self.start_background_task(run_async_handler)
task_reference_holder.add(ret)
ret.add_done_callback(task_reference_holder.discard)
else:
ret = await run_async_handler()
else:
Expand All @@ -502,6 +509,8 @@ async def run_sync_handler():

if run_async:
ret = self.start_background_task(run_sync_handler)
task_reference_holder.add(ret)
ret.add_done_callback(task_reference_holder.discard)
else:
ret = await run_sync_handler()
return ret
Expand Down

0 comments on commit 0729554

Please sign in to comment.