Skip to content

Commit 2668abf

Browse files
committed
Fix EINTR handling
1 parent ccfa938 commit 2668abf

File tree

1 file changed

+33
-10
lines changed
  • crates/vm/src/stdlib

1 file changed

+33
-10
lines changed

crates/vm/src/stdlib/io.rs

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,10 +1001,18 @@ mod _io {
10011001
) -> PyResult<Option<usize>> {
10021002
let len = buf_range.len();
10031003
let res = if let Some(buf) = buf {
1004-
let mem_obj = PyMemoryView::from_buffer_range(buf, buf_range, vm)?.to_pyobject(vm);
1004+
let mem_obj =
1005+
PyMemoryView::from_buffer_range(buf, buf_range, vm)?.into_ref(&vm.ctx);
10051006

1006-
// TODO: loop if write() raises an interrupt
1007-
vm.call_method(self.raw.as_ref().unwrap(), "write", (mem_obj,))?
1007+
// Loop if write() raises EINTR (PEP 475)
1008+
loop {
1009+
let res =
1010+
vm.call_method(self.raw.as_ref().unwrap(), "write", (mem_obj.clone(),));
1011+
match trap_eintr(res, vm)? {
1012+
Some(val) => break val,
1013+
None => continue,
1014+
}
1015+
}
10081016
} else {
10091017
let v = core::mem::take(&mut self.buffer);
10101018
let write_buf = VecBuffer::from(v).into_ref(&vm.ctx);
@@ -1015,8 +1023,16 @@ mod _io {
10151023
)?
10161024
.into_ref(&vm.ctx);
10171025

1018-
// TODO: loop if write() raises an interrupt
1019-
let res = vm.call_method(self.raw.as_ref().unwrap(), "write", (mem_obj.clone(),));
1026+
// Loop if write() raises EINTR (PEP 475)
1027+
let res = loop {
1028+
let res =
1029+
vm.call_method(self.raw.as_ref().unwrap(), "write", (mem_obj.clone(),));
1030+
match trap_eintr(res, vm) {
1031+
Ok(Some(val)) => break Ok(val),
1032+
Ok(None) => continue,
1033+
Err(e) => break Err(e),
1034+
}
1035+
};
10201036

10211037
mem_obj.release();
10221038
self.buffer = write_buf.take();
@@ -5737,11 +5753,18 @@ mod fileio {
57375753

57385754
let mut handle = zelf.get_fd(vm)?;
57395755

5740-
let len = match obj.with_ref(|b| handle.write(b)) {
5741-
Ok(n) => n,
5742-
// Non-blocking mode: return None if EAGAIN
5743-
Err(e) if e.raw_os_error() == Some(libc::EAGAIN) => return Ok(None),
5744-
Err(e) => return Err(Self::io_error(zelf, e, vm)),
5756+
// Loop on EINTR (PEP 475)
5757+
let len = loop {
5758+
match obj.with_ref(|b| handle.write(b)) {
5759+
Ok(n) => break n,
5760+
Err(e) if e.raw_os_error() == Some(libc::EINTR) => {
5761+
vm.check_signals()?;
5762+
continue;
5763+
}
5764+
// Non-blocking mode: return None if EAGAIN
5765+
Err(e) if e.raw_os_error() == Some(libc::EAGAIN) => return Ok(None),
5766+
Err(e) => return Err(Self::io_error(zelf, e, vm)),
5767+
}
57455768
};
57465769

57475770
//return number of bytes written

0 commit comments

Comments
 (0)