The reason will be displayed to describe this comment to others. Learn more.
⚠️ Potential issue | 🟠 Major
🧩 Analysis chain
🏁 Script executed:
# First, let's check if the file exists and get its total line count
wc -l crates/vm/src/stdlib/io.rs
Repository: RustPython/RustPython
Length of output: 96
🏁 Script executed:
# Read the specific lines mentioned in the review (5339 and 5764-5786)# Start with line 5339
sed -n '5335,5345p' crates/vm/src/stdlib/io.rs
Repository: RustPython/RustPython
Length of output: 427
🏁 Script executed:
# Read the lines 5764-5786 to see the full context of the issue
sed -n '5760,5790p' crates/vm/src/stdlib/io.rs
Repository: RustPython/RustPython
Length of output: 1218
🏁 Script executed:
# Also check around line 5767 mentioned in the comment
sed -n '5760,5800p' crates/vm/src/stdlib/io.rs
Repository: RustPython/RustPython
Length of output: 1533
🏁 Script executed:
# Search for crt_fd module usage and definition
rg "crt_fd" crates/vm/src/stdlib/io.rs | head -20
Repository: RustPython/RustPython
Length of output: 859
🏁 Script executed:
# Check the Rust std::io::Read documentation behavior - search for how read_to_end is used elsewhere
rg "read_to_end" crates/vm/src/stdlib/io.rs
Repository: RustPython/RustPython
Length of output: 114
🏁 Script executed:
# Look for crt_fd module definition
fd "crt_fd" crates/
Repository: RustPython/RustPython
Length of output: 92
🏁 Script executed:
# Check if there's a read function being used with crt_fd elsewhere
rg "crt_fd::read" crates/vm/src/stdlib/io.rs
Repository: RustPython/RustPython
Length of output: 222
🏁 Script executed:
# Search for DEFAULT_BUFFER_SIZE constant
rg "DEFAULT_BUFFER_SIZE" crates/vm/src/stdlib/io.rs | head -5
Repository: RustPython/RustPython
Length of output: 360
🏁 Script executed:
# Check the crt_fd module to understand the read function
cat crates/common/src/crt_fd.rs
Repository: RustPython/RustPython
Length of output: 9961
🏁 Script executed:
# Look for the context where crt_fd::read is used in that loop
rg -B5 -A5 "crt_fd::read\(handle" crates/vm/src/stdlib/io.rs
Repository: RustPython/RustPython
Length of output: 1070
Replace read_to_end() with explicit crt_fd::read() loop to preserve signal checking on EINTR.
The current code uses std::io::Read::read_to_end(), which internally retries on EINTR, preventing the outer error handler from triggering vm.check_signals(). This breaks the unbounded-read path (size < 0) signal handling.
Use a chunked read loop with crt_fd::read() instead, which surfaces EINTR to the error handler:
Replace read_to_end() with chunked crt_fd::read() loop
- let mut bytes = vec![];- // Loop on EINTR (PEP 475)- loop {- match vm.allow_threads(|| {- let mut h = handle;- h.read_to_end(&mut bytes)- }) {- Ok(_) => break,- Err(e) if e.raw_os_error() == Some(libc::EINTR) => {- vm.check_signals()?;- continue;- }- // Non-blocking mode: return None if EAGAIN (only if no data read yet)- Err(e) if e.raw_os_error() == Some(libc::EAGAIN) => {- if bytes.is_empty() {- return Ok(None);- }- break;- }- Err(e) => return Err(Self::io_error(zelf, e, vm)),- }- }+ let mut bytes = vec![];+ loop {+ let mut chunk = vec![0; super::DEFAULT_BUFFER_SIZE];+ match vm.allow_threads(|| crt_fd::read(handle, &mut chunk)) {+ Ok(0) => break,+ Ok(n) => bytes.extend_from_slice(&chunk[..n]),+ Err(e) if e.raw_os_error() == Some(libc::EINTR) => {+ vm.check_signals()?;+ continue;+ }+ Err(e) if e.raw_os_error() == Some(libc::EAGAIN) => {+ if bytes.is_empty() {+ return Ok(None);+ }+ break;+ }+ Err(e) => return Err(Self::io_error(zelf, e, vm)),+ }+ }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@crates/vm/src/stdlib/io.rs` at line 5339, The code currently uses
std::io::Read::read_to_end(), which hides EINTR and prevents vm.check_signals()
from running on the unbounded-read path (size < 0); replace that call with an
explicit chunked loop that uses crt_fd::read() to fill a Vec<u8> (read
fixed-size chunks, e.g., 8KiB), append each successful chunk to the buffer,
break on EOF (0 bytes), and on read errors return Err so EINTR is propagated to
the outer error handler; make sure to reference and replace the read_to_end()
call site and keep vm.check_signals() semantics by letting crt_fd::read()
surface EINTR instead of swallowing it.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
All reactions
bitflags::bitflags! {
#[derive(Copy, Clone, Debug, PartialEq)]
Expand DownExpand Up
@@ -5740,12 +5740,12 @@ mod fileio {
"File or stream is not readable".to_owned(),
));
}
let mut handle = zelf.get_fd(vm)?;
let handle = zelf.get_fd(vm)?;
let bytes = if let Some(read_byte) = read_byte.to_usize() {
let mut bytes = vec![0; read_byte];
// Loop on EINTR (PEP 475)
let n = loop {
match handle.read(&mut bytes) {
match vm.allow_threads(|| crt_fd::read(handle, &mut bytes)) {
Ok(n) => break n,
Err(e) if e.raw_os_error() == Some(libc::EINTR) => {
vm.check_signals()?;
Expand All
@@ -5764,7 +5764,10 @@ mod fileio {
let mut bytes = vec![];
// Loop on EINTR (PEP 475)
loop {
match handle.read_to_end(&mut bytes) {
match vm.allow_threads(|| {
let mut h = handle;
h.read_to_end(&mut bytes)
}) {
Ok(_) => break,
Err(e) if e.raw_os_error() == Some(libc::EINTR) => {
vm.check_signals()?;
Expand DownExpand Up
@@ -5802,10 +5805,9 @@ mod fileio {
let handle = zelf.get_fd(vm)?;
let mut buf = obj.borrow_buf_mut();
let mut f = handle.take(buf.len() as _);
// Loop on EINTR (PEP 475)
let ret = loop {
match f.read(&mut buf) {
match vm.allow_threads(|| crt_fd::read(handle, &mut buf)) {
Ok(n) => break n,
Err(e) if e.raw_os_error() == Some(libc::EINTR) => {
vm.check_signals()?;
Expand DownExpand Up
@@ -5835,11 +5837,11 @@ mod fileio {
));
}
let mut handle = zelf.get_fd(vm)?;
let handle = zelf.get_fd(vm)?;
// Loop on EINTR (PEP 475)
let len = loop {
match obj.with_ref(|b| handle.write(b)) {
match obj.with_ref(|b| vm.allow_threads(|| crt_fd::write(handle, b))) {
Ok(n) => break n,
Err(e) if e.raw_os_error() == Some(libc::EINTR) => {
vm.check_signals()?;
Expand Down
Loading
Oops, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Loading
Oops, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.