mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
Handle EINTR retry in os.write() (PEP 475) (#7482)
* Handle EINTR retry in os.write() (PEP 475) Add EINTR retry loop to os.write(), matching the existing pattern in os.read() and os.readinto(). Remove the expectedFailure marker from test_write in _test_eintr.py. * Add atomic snapshot for dict/dict_keys in extract_elements Add fast paths for dict and dict_keys types in extract_elements_with, matching _list_extend() in CPython Objects/listobject.c. Each branch takes an atomic snapshot under a single read lock, preventing race conditions from concurrent dict mutation without the GIL. Remove expectedFailure from test_thread_safety.
This commit is contained in:
1 parent
c0d829e75c
commit
0504ea2675
4 files changed
+23
-13
No files matched your search
Vendored
-1
@@ -163,7 +163,6 @@ class OSEINTRTest(EINTRBaseTest):
|
||||
self.assertEqual(os.readinto(fd, buffer), len(expected))
|
||||
self.assertEqual(buffer, expected)
|
||||
|
||||
@unittest.expectedFailure # TODO: RUSTPYTHON; InterruptedError: [Errno 4] Interrupted system call
|
||||
def test_write(self):
|
||||
rd, wr = os.pipe()
|
||||
self.addCleanup(os.close, wr)
|
||||
|
||||
Vendored
-2
@@ -4814,8 +4814,6 @@ class _TestFinalize(BaseTestCase):
|
||||
self.assertEqual(result, ['a', 'b', 'd10', 'd03', 'd02', 'd01', 'e'])
|
||||
|
||||
@support.requires_resource('cpu')
|
||||
# TODO: RUSTPYTHON; dict iteration races with concurrent GC mutations
|
||||
@unittest.expectedFailure
|
||||
def test_thread_safety(self):
|
||||
# bpo-24484: _run_finalizers() should be thread-safe
|
||||
def cb():
|
||||
|
||||
@@ -321,12 +321,19 @@ pub(super) mod _os {
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn write(
|
||||
fd: crt_fd::Borrowed<'_>,
|
||||
data: ArgBytesLike,
|
||||
vm: &VirtualMachine,
|
||||
) -> io::Result<usize> {
|
||||
data.with_ref(|b| vm.allow_threads(|| crt_fd::write(fd, b)))
|
||||
fn write(fd: crt_fd::Borrowed<'_>, data: ArgBytesLike, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
data.with_ref(|b| {
|
||||
loop {
|
||||
match vm.allow_threads(|| crt_fd::write(fd, b)) {
|
||||
Ok(n) => return Ok(n),
|
||||
Err(e) if e.raw_os_error() == Some(libc::EINTR) => {
|
||||
vm.check_signals()?;
|
||||
continue;
|
||||
}
|
||||
Err(e) => return Err(e.into_pyexception(vm)),
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
|
||||
+10
-4
@@ -22,7 +22,7 @@ use crate::{
|
||||
self, PyBaseExceptionRef, PyDict, PyDictRef, PyInt, PyList, PyModule, PyStr, PyStrInterned,
|
||||
PyStrRef, PyTypeRef, PyUtf8Str, PyUtf8StrInterned, PyWeak,
|
||||
code::PyCode,
|
||||
dict::{PyDictItems, PyDictValues},
|
||||
dict::{PyDictItems, PyDictKeys, PyDictValues},
|
||||
pystr::AsPyStr,
|
||||
tuple::PyTuple,
|
||||
},
|
||||
@@ -1822,7 +1822,9 @@ impl VirtualMachine {
|
||||
where
|
||||
F: Fn(PyObjectRef) -> PyResult<T>,
|
||||
{
|
||||
// Extract elements from item, if possible:
|
||||
// Type-specific fast paths corresponding to _list_extend() in CPython
|
||||
// Objects/listobject.c. Each branch takes an atomic snapshot to avoid
|
||||
// race conditions from concurrent mutation (no GIL).
|
||||
let cls = value.class();
|
||||
let list_borrow;
|
||||
let slice = if cls.is(self.ctx.types.tuple_type) {
|
||||
@@ -1830,8 +1832,13 @@ impl VirtualMachine {
|
||||
} else if cls.is(self.ctx.types.list_type) {
|
||||
list_borrow = value.downcast_ref::<PyList>().unwrap().borrow_vec();
|
||||
&list_borrow
|
||||
} else if cls.is(self.ctx.types.dict_type) {
|
||||
let keys = value.downcast_ref::<PyDict>().unwrap().keys_vec();
|
||||
return keys.into_iter().map(func).collect();
|
||||
} else if cls.is(self.ctx.types.dict_keys_type) {
|
||||
let keys = value.downcast_ref::<PyDictKeys>().unwrap().dict.keys_vec();
|
||||
return keys.into_iter().map(func).collect();
|
||||
} else if cls.is(self.ctx.types.dict_values_type) {
|
||||
// Atomic snapshot of dict values - prevents race condition during iteration
|
||||
let values = value
|
||||
.downcast_ref::<PyDictValues>()
|
||||
.unwrap()
|
||||
@@ -1839,7 +1846,6 @@ impl VirtualMachine {
|
||||
.values_vec();
|
||||
return values.into_iter().map(func).collect();
|
||||
} else if cls.is(self.ctx.types.dict_items_type) {
|
||||
// Atomic snapshot of dict items - prevents race condition during iteration
|
||||
let items = value
|
||||
.downcast_ref::<PyDictItems>()
|
||||
.unwrap()
|
||||
|
||||
Reference in new issue
Block a user