Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 25 additions & 18 deletions crates/stdlib/src/overlapped.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1134,32 +1134,39 @@ mod _overlapped {
let olderr = host_winapi::get_last_error();

// Cancel pending I/O and wait for completion
if !host_overlapped::has_overlapped_io_completed(&inner.overlapped)
let pending_error = if !host_overlapped::has_overlapped_io_completed(&inner.overlapped)
&& !matches!(inner.data, OverlappedData::NotStarted)
{
match host_overlapped::cancel_overlapped_for_drop(inner.handle, &inner.overlapped)
.error
{
ERROR_SUCCESS | ERROR_NOT_FOUND | ERROR_OPERATION_ABORTED => {}
_ => {
let msg = format!(
"{zelf:?} still has pending operation at deallocation, the process may crash"
);
let exc = vm.new_runtime_error(msg);
let err_msg = Some(format!(
"Exception ignored while deallocating overlapped operation {zelf:?}"
));
let obj: PyObjectRef = zelf.to_owned().into();
vm.run_unraisable(exc, err_msg, obj);
}
}
}
!matches!(
vm.allow_threads(|| host_overlapped::cancel_overlapped_for_drop(
inner.handle,
&inner.overlapped
))
.error,
ERROR_SUCCESS | ERROR_NOT_FOUND | ERROR_OPERATION_ABORTED
)
} else {
false
};

// Close the event handle
if !inner.overlapped.hEvent.is_null() {
let _ = host_winapi::close_handle(inner.overlapped.hEvent);
inner.overlapped.hEvent = core::ptr::null_mut();
}
// Debug formatting takes inner again; the unraisable hook can also
// re-enter this object. Complete native cleanup before either runs.
drop(inner);
if pending_error {
let msg = format!(
"{zelf:?} still has pending operation at deallocation, the process may crash"
);
let exc = vm.new_runtime_error(msg);
let err_msg = Some(format!(
"Exception ignored while deallocating overlapped operation {zelf:?}"
));
vm.run_unraisable(exc, err_msg, vm.ctx.none());
}

// Restore last error
host_windows::set_last_error(olderr);
Expand Down
13 changes: 13 additions & 0 deletions extra_tests/snippets/stdlib_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,23 @@
these only run where they are reachable.
"""

import subprocess
import sys

from testutils import assert_raises

# An unclosed event loop must not deadlock during interpreter shutdown.
subprocess.run(
[
sys.executable,
"-c",
"import asyncio; loop = asyncio.new_event_loop(); "
"asyncio.set_event_loop(loop); loop.run_until_complete(asyncio.sleep(0))",
],
check=True,
timeout=10,
)

if sys.implementation.name != "rustpython":
sys.exit(0)

Expand Down
Loading