Skip to content

Async callbacks tasks is not kept and might be GC before the callback is run #1938

Open
@sveinse

Description

@sveinse

The can rx message handler in class Notifier is creating tasks when runs in async mode and gets a coroutine callback.

python-can/can/notifier.py

Lines 143 to 148 in 5d62394

def _on_message_received(self, msg: Message) -> None:
for callback in self.listeners:
res = callback(msg)
if res and self._loop and asyncio.iscoroutine(res):
# Schedule coroutine
self._loop.create_task(res)

However the python docs is clear that the reference to the task needs to be kept to ensure its not garbage collected: https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task

The fix should be fairly straight forward:

    def _on_message_received(self, msg: Message) -> None:
        for callback in self.listeners:
            res = callback(msg)
            if res and self._loop and asyncio.iscoroutine(res):
                # Schedule coroutine
                # In __init__: self._tasks: set[asyncio.Task] = set()
                task = self._loop.create_task(res)
                self._tasks.add(task)
                task.add_done_callback(self._tasks.discard)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions