mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Wait for overlapped WriteFile completion in Rust (#7383)
On Windows, SimpleQueue skips write locking because pipe writes are assumed atomic. Without GIL, PipeConnection. _send_bytes races on _send_ov when multiple threads call send_bytes concurrently (e.g. _terminate_pool vs workers). Wait for pending overlapped writes inside WriteFile before returning to Python, so ERROR_IO_PENDING is never exposed and the _send_ov assignment window is negligible.
This commit is contained in:
1 parent
fbab8fc5be
commit
0046c627f1
1 file changed
+20
@@ -1251,6 +1251,26 @@ mod _winapi {
|
||||
|
||||
err
|
||||
};
|
||||
|
||||
// Without GIL, the Python-level PipeConnection._send_bytes has a
|
||||
// race on _send_ov when the caller (SimpleQueue) skips locking on
|
||||
// Windows. Wait for completion here so the caller never sees
|
||||
// ERROR_IO_PENDING and never blocks in WaitForMultipleObjects,
|
||||
// keeping the _send_ov window negligibly small.
|
||||
if err == ERROR_IO_PENDING {
|
||||
let event = ov.inner.lock().overlapped.hEvent;
|
||||
vm.allow_threads(|| unsafe {
|
||||
windows_sys::Win32::System::Threading::WaitForSingleObject(
|
||||
event,
|
||||
windows_sys::Win32::System::Threading::INFINITE,
|
||||
);
|
||||
});
|
||||
let result = vm
|
||||
.ctx
|
||||
.new_tuple(vec![ov.into_pyobject(vm), vm.ctx.new_int(0u32).into()]);
|
||||
return Ok(result.into());
|
||||
}
|
||||
|
||||
let result = vm
|
||||
.ctx
|
||||
.new_tuple(vec![ov.into_pyobject(vm), vm.ctx.new_int(err).into()]);
|
||||
|
||||
Reference in new issue
Block a user