BQSKit / bqskit

Berkeley Quantum Synthesis Toolkit
Other
113 stars 32 forks source link

RuntimeWarnings from `get_runtime().cancel(future)` #262

Closed WolfLink closed 4 weeks ago

WolfLink commented 1 month ago

I have some code of the form:

my_future = get_runtime().map(...)

result1 = get_runtime().next(my_future)
result2 = get_runtime().next(my_future)

get_runtime().cancel(my_future)

I get warning messages of the form:

myvenv/lib/python3.10/site-packages/bqskit/utils/cachedclass.py:45: RuntimeWarning: coroutine 'RuntimeTask.run' was never awaited
  hash_a = all(
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

The line hash_a = all( is a seemingly random line of code each time. Note that the warnings don't show up every time; but they seem to show up more frequently when my CPU is under heavy load.

It seems to be related to get_runtime().cancel(my_future) because if I replace that line with await my_future I no longer see the warnings (but the code takes undersireably longer obviously).

WolfLink commented 1 month ago

So I found the issue. You are supposed to close() coroutines if you aren't going to await them. (It's also safe to close() a coroutine after it has been awaited). Neither happens when a task gets cancelled currently.

Relevant StackOverflow: https://stackoverflow.com/questions/62045387/how-to-suppress-coroutine-was-never-awaited-warning

I have two possible fixes to suggest:

  1. The easier way is to simply implement __del__ for RuntimeTask which will close its coroutine.
  2. The more explicit way would be to go close() all relevant coroutines when cancel gets called.

The 1st approach is a lot simpler. I'm pretty sure the warning happens when the unused coroutine gets garbage collected, so this approach is just letting python know it was ok for that coroutine to go unused.

The 2nd approach is a lot more work to implement, but it has a benfit in that if there is some future bug where a RuntimeTask falls through the cracks when it wasn't supposed to be cancelled, the warning might pop up to let you know. The 1st approach will make it so any time a RuntimeTask is never executed for any reason, the warning will not appear.