-
-
Notifications
You must be signed in to change notification settings - Fork 33.2k
Description
Crash report
What happened?
Also falls under: RuntimeError: <_overlapped.Overlapped object at 0x<address>> still has pending operation at deallocation, the process may crash.
We have an application that embeds Python and needs to tick the event loop once (or more) per frame. Generally this is done with the event loop idiom: stop() / run_forever() (once #110771 is available we intend to use that but our workaround is keeping the event loop running between frames similar to #110773 ).
(On my machine this has an 80% chance of printing the above error within 60 seconds, higher the longer it runs)
import asyncio
import threading
import time
main_loop = asyncio.get_event_loop_policy().new_event_loop()
assert isinstance(main_loop, asyncio.ProactorEventLoop)
def threadMain():
while True:
main_loop.call_soon_threadsafe(lambda: None)
time.sleep(0.01)
thr = threading.Thread(target=threadMain, daemon=True)
thr.start()
while True:
main_loop.stop()
main_loop.run_forever()Initial diagnosis
Typically when the "still has pending operation" error message is printed, _overlapped_Overlapped_cancel_impl() will have been called which will call CancelIoEx() (returns TRUE).
When Overlapped_dealloc() is called and overlapped IO has not completed, CancelIoEx() is called again, returning FALSE with GLE=ERROR_NOT_FOUND (because the previous cancel succeeded). The existing code then releases the GIL and calls GetOverlappedResult() (wait = FALSE) which also returns FALSE with GLE=ERROR_IO_PENDING. Since Windows is not done with the OVERLAPPED struct the error message is printed and the memory is dangerously freed.
Changing wait = TRUE if either the _overlapped_Overlapped_cancel_impl() call to CancelIoEx() succeeds, or the one in Overlapped_dealloc() succeeds will result in a hang: GetOverlappedResult() will never return. This is because IO Completion Ports are in use and GetQueuedCompletionStatus() needs to be queried until it returns the OVERLAPPED in question.
CPython versions tested on:
3.10, 3.11, CPython main branch
Operating systems tested on:
Windows
Output from running 'python -VV' on the command line:
Python 3.13.0a4+ (heads/main:bb66600558, Mar 13 2024, 18:46:58) [MSC v.1938 64 bit (AMD64)]
Linked PRs
- gh-116773: Fix overlapped memory corruption issue #116774
- [3.12] gh-116773: Fix overlapped memory corruption crash (GH-116774) #117078
- [3.11] gh-116773: Fix overlapped memory corruption crash (GH-116774) #117077
- [3.10] gh-116773: Fix overlapped memory corruption crash (GH-116774) #117079
- [3.9] gh-116773: Fix overlapped memory corruption crash (GH-116774) #117080
- [3.8] gh-116773: Fix overlapped memory corruption crash (GH-116774) #117083