New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test_asyncio: ProactorEventLoopTests sendfile tests leak references on Windows #76891
Comments
AMD64 Windows8.1 Refleaks 3.x: test_asyncio leaked [4, 4, 3] memory blocks, sum=11 I reproduced the issue. I'm running test.bisect to try to isolate this bug. |
It seems to be related to sendfile(): C:\vstinner\python\master>python -m test -R 3:3 test_asyncio -m test.test_asyncio.test_events.ProactorEventLoopTests.test_sendfile_close_peer_in_middle_of_receiving 1 test failed: Total duration: 1 sec |
Andrew, please take a look. I'll have very limited (to no at all) time to work on Python in the next 2 weeks. |
The test is still leaking memory blocks. Any progress on investigating the issue? |
Oh, I found again this bug while working on my PR 7827 (detect handle leaks on Windows in regrtest). |
Update:
I spent a lot of time to investigate test_sendfile_fallback_close_peer_in_the_middle_of_receiving() leak and I don't understand the issue. The main loop is BaseEventLoop._sendfile_fallback(). For the specific case of this test, the loop can be simplified to: proto = _SendfileFallbackProtocol(transp)
try:
while True:
data = b'x' * (1024 * 64)
await proto.drain()
transp.write(data)
finally:
await proto.restore() The server closes the connection after it gets 1024 bytes. The client socket gets a ConnectionAbortedError exception in _ProactorBaseWritePipeTransport._loop_writing() which calls _fatal_error(): except OSError as exc:
self._fatal_error(exc, 'Fatal write error on pipe transport') _fatal_error() calls _force_close() which sets _closing to True and calls protocol.connection_lost(). In the meanwhile, drain() raises ConnectionError because is_closing() is true: async def drain(self):
if self._transport.is_closing():
raise ConnectionError("Connection closed by peer")
... |
Interesting commit. No idea if it's related. commit 79790bc
|
Attached test_aiosend.py is a simplified version of test to trigger the reference leak. Copy it to Lib/test/ and run: vstinner@WIN C:\vstinner\python\master>python -m test test_aiosend -R 3:3 == Tests result: FAILURE == 1 test failed: Total duration: 548 ms |
It took me 1 year, a few sleepless nights, multiple attempts to understand the leak, but I eventually found it! WSASend() doesn't release the memory if it fails immediately. I wrote PR 11469 to fix the memory leak. ReadFile() has the same bug, I also fixed it. By the way, the _overlapped.Overlapped type has no traverse function: it may help the garbage collector to add once, since asyncio is famous for building reference cycles by design (Future.set_exception()). |
I ran test_asyncio refleak hunting on Windows, and there is no more leak! vstinner@WIN C:\vstinner\python\master>python -m test test_asyncio -R 3:3 I will close this PR once the 3.7 backport is merged. |
Ok, _overlapped.Overlapped should now have a few less memory leaks :-) |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: