Closed MatthewScholefield closed 3 years ago
Thank you for the PR I didn't know an unreferenced task could be garbage-collected.
Just one question: should we set to None the variables that keep the reference on __aexit__
(to prevent some kind of circular reference that leaks the TestClients)?
Merging #35 (8d7f657) into master (d1b93fa) will increase coverage by
0.15%
. The diff coverage is100.00%
.
@@ Coverage Diff @@
## master #35 +/- ##
==========================================
+ Coverage 87.25% 87.40% +0.15%
==========================================
Files 6 6
Lines 400 405 +5
==========================================
+ Hits 349 354 +5
Misses 51 51
Impacted Files | Coverage Δ | |
---|---|---|
async_asgi_testclient/testing.py | 88.73% <100.00%> (+0.24%) |
:arrow_up: |
async_asgi_testclient/websocket.py | 74.11% <100.00%> (+0.62%) |
:arrow_up: |
Continue to review full report at Codecov.
Legend - Click here to learn more
Δ = absolute <relative> (impact)
,ø = not affected
,? = missing data
Powered by Codecov. Last update d1b93fa...8d7f657. Read the comment docs.
Just one question: should we set to None the variables that keep the reference on
__aexit__
(to prevent some kind of circular reference that leaks the TestClients)?
Good point. I don't think circular references are a problem for the most part in Python (although there are some edge cases), but setting them to None
there definitely makes sense just from a logical perspective. I've pushed a change to implement that.
Thank you very much. v1.4.6 released
This fixes issues with asyncio and garbage collection. Specifically, if a running task within
asyncio
doesn't have a hard reference, it can be garbage collected causing a number of strange errors likeTask was destroyed but it is pending!
. Holding a hard reference to running tasks solves this issue which is what this PR does.To consistently replicate this error we can force garbage collection in between every step of the event loop as follows:
/usr/lib/python3.*/asyncio/base_events.py
and withindef _run_once
, near the bottom immediately within thefor i in range(ntodo):
, addimport gc; gc.collect()
asyncio
(rather thanuvloop
for example) so that it runs the code we just modified (pytest does by default)