Visitar URL original
Implement Windows SemLock in _multiprocessing module by youknowone · Pull Request #7199 · RustPython/RustPython · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Remove expectedFailure for tests now passing with Windows SemLock
  • Loading branch information
youknowone committed Feb 23, 2026
commit c40092bcce84637bf057d5559d17e9b66adc1948
2 changes: 0 additions & 2 deletions Lib/test/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -4119,8 +4119,6 @@ def test_90195(self):
# Logger should be enabled, since explicitly mentioned
self.assertFalse(logger.disabled)

# TODO: RUSTPYTHON - SemLock not implemented on Windows
@unittest.expectedFailureIfWindows("TODO: RUSTPYTHON")
def test_111615(self):
# See gh-111615
import_helper.import_module('_multiprocessing') # see gh-113692
Expand Down
1 change: 0 additions & 1 deletion Lib/test/test_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -6620,7 +6620,6 @@ def remoteProcessServer(cls, q):
s2.close()
s.close()

@unittest.expectedFailure # TODO: RUSTPYTHON; multiprocessing.SemLock not implemented
def testShare(self):
# Transfer the listening server socket to another process
# and service it from there.
Expand Down
29 changes: 14 additions & 15 deletions crates/stdlib/src/multiprocessing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,14 @@ mod _multiprocessing {
};
use core::sync::atomic::{AtomicI32, AtomicU32, Ordering};
use windows_sys::Win32::Foundation::{
CloseHandle, HANDLE, INVALID_HANDLE_VALUE, WAIT_EVENT, WAIT_OBJECT_0,
CloseHandle, ERROR_TOO_MANY_POSTS, HANDLE, INVALID_HANDLE_VALUE, WAIT_FAILED,
WAIT_OBJECT_0, WAIT_TIMEOUT,
};
use windows_sys::Win32::Networking::WinSock::{self, SOCKET};
use windows_sys::Win32::System::Threading::{
CreateSemaphoreW, GetCurrentThreadId, ReleaseSemaphore, WaitForSingleObjectEx,
CreateSemaphoreW, GetCurrentThreadId, INFINITE, ReleaseSemaphore, WaitForSingleObjectEx,
};

const INFINITE: u32 = 0xFFFFFFFF;
const WAIT_TIMEOUT: WAIT_EVENT = 258; // 0x102
const WAIT_FAILED: WAIT_EVENT = 0xFFFFFFFF;
const ERROR_TOO_MANY_POSTS: u32 = 298;

// These match the values in Lib/multiprocessing/synchronize.py
const RECURSIVE_MUTEX: i32 = 0;
const SEMAPHORE: i32 = 1;
Expand Down Expand Up @@ -171,11 +167,15 @@ mod _multiprocessing {
}

// Check whether we can acquire without blocking
if unsafe { WaitForSingleObjectEx(self.handle.as_raw(), 0, 0) } == WAIT_OBJECT_0 {
self.last_tid
.store(unsafe { GetCurrentThreadId() }, Ordering::Release);
self.count.fetch_add(1, Ordering::Release);
return Ok(true);
match unsafe { WaitForSingleObjectEx(self.handle.as_raw(), 0, 0) } {
WAIT_OBJECT_0 => {
self.last_tid
.store(unsafe { GetCurrentThreadId() }, Ordering::Release);
self.count.fetch_add(1, Ordering::Release);
return Ok(true);
}
WAIT_FAILED => return Err(vm.new_last_os_error()),
_ => {}
}

// Poll with signal checking (CPython uses WaitForMultipleObjectsEx
Expand All @@ -193,8 +193,7 @@ mod _multiprocessing {
remaining.min(poll_ms)
};

let res =
unsafe { WaitForSingleObjectEx(self.handle.as_raw(), wait_ms, 0) };
let res = unsafe { WaitForSingleObjectEx(self.handle.as_raw(), wait_ms, 0) };

match res {
WAIT_OBJECT_0 => {
Expand All @@ -213,7 +212,7 @@ mod _multiprocessing {
_ => {
return Err(vm.new_runtime_error(format!(
"WaitForSingleObject() gave unrecognized value {res}"
)))
)));
}
}
}
Expand Down
13 changes: 6 additions & 7 deletions crates/vm/src/exceptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2061,18 +2061,17 @@ pub(super) mod types {
if !vm.is_none(&filename) {
let mut args_reduced: Vec<PyObjectRef> = vec![errno, msg, filename];

let filename2 =
obj.get_attr("filename2", vm).ok().filter(|f| !vm.is_none(f));
let filename2 = obj
.get_attr("filename2", vm)
.ok()
.filter(|f| !vm.is_none(f));
#[cfg(windows)]
let winerror =
obj.get_attr("winerror", vm).ok().filter(|w| !vm.is_none(w));
let winerror = obj.get_attr("winerror", vm).ok().filter(|w| !vm.is_none(w));

if let Some(filename2) = filename2 {
#[cfg(windows)]
{
args_reduced.push(
winerror.unwrap_or_else(|| vm.ctx.none()),
);
args_reduced.push(winerror.unwrap_or_else(|| vm.ctx.none()));
}
#[cfg(not(windows))]
args_reduced.push(vm.ctx.none());
Expand Down