Skip to content

Commit 00129ea

Browse files
committed
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.
1 parent 8c01615 commit 00129ea

File tree

2 files changed

+13
-7
lines changed

2 files changed

+13
-7
lines changed

Lib/test/_test_eintr.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ def test_readinto(self):
163163
self.assertEqual(os.readinto(fd, buffer), len(expected))
164164
self.assertEqual(buffer, expected)
165165

166-
@unittest.expectedFailure # TODO: RUSTPYTHON; InterruptedError: [Errno 4] Interrupted system call
167166
def test_write(self):
168167
rd, wr = os.pipe()
169168
self.addCleanup(os.close, wr)

crates/vm/src/stdlib/os.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -321,12 +321,19 @@ pub(super) mod _os {
321321
}
322322

323323
#[pyfunction]
324-
fn write(
325-
fd: crt_fd::Borrowed<'_>,
326-
data: ArgBytesLike,
327-
vm: &VirtualMachine,
328-
) -> io::Result<usize> {
329-
data.with_ref(|b| vm.allow_threads(|| crt_fd::write(fd, b)))
324+
fn write(fd: crt_fd::Borrowed<'_>, data: ArgBytesLike, vm: &VirtualMachine) -> PyResult<usize> {
325+
data.with_ref(|b| {
326+
loop {
327+
match vm.allow_threads(|| crt_fd::write(fd, b)) {
328+
Ok(n) => return Ok(n),
329+
Err(e) if e.raw_os_error() == Some(libc::EINTR) => {
330+
vm.check_signals()?;
331+
continue;
332+
}
333+
Err(e) => return Err(e.into_pyexception(vm)),
334+
}
335+
}
336+
})
330337
}
331338

332339
#[cfg(not(windows))]

0 commit comments

Comments
 (0)