question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Waitables passed into First can leak Tasks

See original GitHub issue

I’ve run into an issue where I had a simulation that slowed substantially as time passed. I eventually traced this to the fact that within the scheduler, there were an excessive number of coroutines waiting on the rising edge of my clock. Further investigation, with the help of @ktbarrett and @marlonjames revealed the issue related to the way I was using First. I was passing a Waitable into First, in this case the ClockCycles trigger. This first was awaited in a while loop and was frequently awaited upon.

while True:
   await First(ClockCycles, RisingEdge)
   #other logic here

The rising edge trigger frequently fired and the number of clock cycles in the ClockCycles trigger was very large. The issue appears to be with the fact First._wait calls wait_callback which in turn makes a call to scheduler._trigger_from_any. I am told scheduler._trigger_from_any creates a new task and this task is not cleaned up by First. This is the mechanism by which First leaks tasks.

Let me know if example code is helpful and I’ll be happy to try to create a simple test case.

Environment:

  • Cocotb 1.5.2 and 1.6.1
  • Alma Linux 8.5
  • Riviera Pro 2021.10 64 bit
  • Custom Installation of Python 3.7

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:6 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
marlonjamescommented, May 5, 2022

First._wait creates a new task for each trigger with the _wait_callback coroutine function (line 884): https://github.com/cocotb/cocotb/blob/b4a2ce033fb21b10e2a2deb0dbb95d0b9e895e9c/cocotb/triggers.py#L873-L884

_wait_callback uses scheduler._trigger_from_any: https://github.com/cocotb/cocotb/blob/b4a2ce033fb21b10e2a2deb0dbb95d0b9e895e9c/cocotb/triggers.py#L802-L809

scheduler._trigger_from_any calls scheduler._trigger_from_waitable, which creates another new Task: https://github.com/cocotb/cocotb/blob/b4a2ce033fb21b10e2a2deb0dbb95d0b9e895e9c/cocotb/scheduler.py#L867-L868

When the RisingEdge trigger fires, First._wait kills the Task waiting in _wait_callback, but that does not kill the extra Task created from the ClockCycles waitable.

In this situation, ClockCycles._wait is a long-lived coroutine, so each time the loop executes, another leaked Task is created and the old ones are still running.

0reactions
ktbarrettcommented, May 5, 2022

Actually I guess it’s possible to yield Waitables and coroutines and other things from generator-based coroutines. IMO this is something that the @cocotb.coroutine decorator should handle not the scheduler. It should bridge yielded objects using yield from the object’s __await__, much like asyncio.coroutine does. More ideally, since we are Python 3.6+ now, we can drop the decorator after 1.7.

Read more comments on GitHub >

github_iconTop Results From Across the Web

wait() with timeout #36217 - JuliaLang/julia - GitHub
The two implementations suggested here seem to leak tasks. It might be possible to avoid this by using Timer since it's close -able....
Read more >
Trio's core functionality — Trio 0.21.0+dev documentation
This allows a CancelScope to be created in one task and passed to another, so that the first task can later cancel some...
Read more >
Leaks when passing NSInputSteam to… - Apple Developer
Leaks when passing NSInputSteam to completionhandler in URLSession:task:needNewBodyStream: ... I am creating a library for HTTPS access using NSURLSession. My ...
Read more >
Source code for cocotb.triggers
Attribute setting and getting will still go through the slot machinery # first, as "data descriptors" take priority over dict access __slots__ =...
Read more >
4 Types of Memory Leaks in JavaScript and How to Get Rid Of ...
In this article we will explore common types of memory leaks in client-side JavaScript code. We will also learn how to use the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found