diff --git a/src/engineio/async_client.py b/src/engineio/async_client.py index 07fe2df0..c2a922eb 100644 --- a/src/engineio/async_client.py +++ b/src/engineio/async_client.py @@ -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. @@ -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) @@ -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) diff --git a/src/engineio/async_server.py b/src/engineio/async_server.py index d1edf590..a7763830 100644 --- a/src/engineio/async_server.py +++ b/src/engineio/async_server.py @@ -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. @@ -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: @@ -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