Save errno inside allow_threads in semaphore acquire#7391
Save errno inside allow_threads in semaphore acquire#7391youknowone merged 1 commit intoRustPython:mainfrom
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughSaves errno immediately inside vm.allow_threads-wrapped blocking semaphore waits and uses that saved value for subsequent error handling and retry logic on Unix and macOS; adds a centralized helper to translate saved errno. Also reformats unsafe tuple freelist access without behavior change. Changes
Sequence Diagram(s)sequenceDiagram
participant VM as VM (allow_threads)
participant Thread as Worker Thread
participant OS as OS semaphore (sem_wait / sem_timedwait)
participant Signals as Signal subsystem
rect rgba(200,200,255,0.5)
Thread->>VM: enter vm.allow_threads (release GIL)
end
rect rgba(200,255,200,0.5)
Thread->>OS: call sem_wait / sem_timedwait
OS-->>Thread: return (r, errno) // captured immediately as saved_errno
end
alt saved_errno == 0
Thread->>VM: reacquire GIL and return success (true)
else saved_errno == EAGAIN or ETIMEDOUT
Thread->>VM: reacquire GIL and return false
else saved_errno == EINTR
Thread->>Signals: check pending signals
Signals-->>Thread: signal handled? (may raise)
Thread->>OS: retry or propagate
else other errno
Thread->>VM: reacquire GIL and return os_error(saved_errno)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
crates/stdlib/src/multiprocessing.rs (1)
721-744: Extract the repeated wait/errno wrapper.Lines 721-744 and 781-791 duplicate the same
allow_threads+(res, errno)packaging. A tiny local helper would keep the platform branches focused on which wait primitive they call and reduce the chance of one path drifting from the others.As per coding guidelines, "When branches differ only in a value but share common logic, extract the differing value first, then call the common logic once to avoid duplicate code."
Also applies to: 781-791
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/stdlib/src/multiprocessing.rs` around lines 721 - 744, The sem_wait/sem_timedwait branches duplicate the same vm.allow_threads wrapper and (r, errno) packaging; create a small local helper (e.g., run_wait_and_errno or a closure) that takes a zero-argument FnOnce calling the desired wait primitive (call sites: libc::sem_timedwait and libc::sem_wait) and returns the (r, Errno) tuple after running it inside vm.allow_threads, then replace both duplicated blocks with calls to that helper so only the differing wait call remains in each branch.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@crates/stdlib/src/multiprocessing.rs`:
- Around line 714-748: The initial assignment let mut saved_errno =
Errno::UnknownErrno is never read because every code path that uses saved_errno
assigns it first; remove the dead initialization and declare saved_errno as an
uninitialized variable that is assigned in the branches that set it (or use
Option<Errno>), i.e., change the declaration near saved_errno and ensure the
non-Apple loop (where vm.allow_threads calls calling
libc::sem_timedwait/sem_wait), and the Apple non-deadline loop assign
saved_errno before it is used in the subsequent match; reference saved_errno,
Errno::UnknownErrno, vm.allow_threads, libc::sem_timedwait, libc::sem_wait and
res when making the adjustment.
---
Nitpick comments:
In `@crates/stdlib/src/multiprocessing.rs`:
- Around line 721-744: The sem_wait/sem_timedwait branches duplicate the same
vm.allow_threads wrapper and (r, errno) packaging; create a small local helper
(e.g., run_wait_and_errno or a closure) that takes a zero-argument FnOnce
calling the desired wait primitive (call sites: libc::sem_timedwait and
libc::sem_wait) and returns the (r, Errno) tuple after running it inside
vm.allow_threads, then replace both duplicated blocks with calls to that helper
so only the differing wait call remains in each branch.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 87fae19d-e9e9-4f6a-a4fe-1c4ebf7a9693
📒 Files selected for processing (1)
crates/stdlib/src/multiprocessing.rs
bb5fa6b to
cd304a5
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (1)
crates/stdlib/src/multiprocessing.rs (1)
714-714:⚠️ Potential issue | 🟡 MinorDrop the dead
saved_errnoinitializer.Line 714 is overwritten on every path that can reach the later
match, so theErrno::UnknownErrnoassignment is never read and will keepclippy::unused_assignmentsnoisy.♻️ Proposed fix
- let mut saved_errno = Errno::UnknownErrno; + let mut saved_errno = None; @@ - saved_errno = e; + saved_errno = Some(e); @@ - if saved_errno == Errno::EINTR { + if saved_errno == Some(Errno::EINTR) { @@ - saved_errno = e; + saved_errno = Some(e); @@ - if saved_errno == Errno::EINTR { + if saved_errno == Some(Errno::EINTR) { @@ - match saved_errno { + match saved_errno.expect("errno must be captured when sem_*wait fails") {As per coding guidelines "Always run clippy to lint Rust code (
cargo clippy) before completing tasks and fix any warnings or lints that are introduced by your changes".Also applies to: 747-747, 752-752, 793-793, 797-797, 808-808
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/stdlib/src/multiprocessing.rs` at line 714, The local variable saved_errno is being assigned Errno::UnknownErrno but that value is always overwritten before use; remove the dead initializer and declare the variable with its type only (e.g., change "let mut saved_errno = Errno::UnknownErrno;" to "let mut saved_errno: Errno;") so the initial assignment is not emitted and clippy's unused_assignments warning is resolved; make the same change for the other occurrences of saved_errno in multiprocessing.rs (the other mentioned spots) so each is declared with a type but without the unused default value.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@crates/stdlib/src/multiprocessing.rs`:
- Line 714: The local variable saved_errno is being assigned Errno::UnknownErrno
but that value is always overwritten before use; remove the dead initializer and
declare the variable with its type only (e.g., change "let mut saved_errno =
Errno::UnknownErrno;" to "let mut saved_errno: Errno;") so the initial
assignment is not emitted and clippy's unused_assignments warning is resolved;
make the same change for the other occurrences of saved_errno in
multiprocessing.rs (the other mentioned spots) so each is declared with a type
but without the unused default value.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: cbadff0b-b4e7-40e7-a2e2-3a77e7645a7b
📒 Files selected for processing (1)
crates/stdlib/src/multiprocessing.rs
cd304a5 to
8ec74ef
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/stdlib/src/multiprocessing.rs (1)
783-795: Consider extracting the duplicatedsem_waitclosure pattern.The
vm.allow_threadsclosure wrappingsem_waitwith errno capture (lines 783-793) is identical to the non-Apple version (lines 733-744). This could be extracted into a helper function to reduce duplication:♻️ Suggested helper extraction
fn sem_wait_with_errno( vm: &VirtualMachine, sem_ptr: *mut sem_t, ) -> (libc::c_int, Errno) { vm.allow_threads(|| { let r = unsafe { libc::sem_wait(sem_ptr) }; (r, if r < 0 { Errno::last() } else { Errno::from_raw(0) }) }) }Then both paths would call:
let (r, e) = sem_wait_with_errno(vm, sem_ptr);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/stdlib/src/multiprocessing.rs` around lines 783 - 795, Extract the duplicated vm.allow_threads closure that calls libc::sem_wait and captures errno into a helper function (e.g., fn sem_wait_with_errno(vm: &VirtualMachine, sem_ptr: *mut sem_t) -> (libc::c_int, Errno)) and replace both occurrences with let (r, e) = sem_wait_with_errno(vm, sem_ptr); so the logic inside sem_wait_with_errno performs the unsafe libc::sem_wait(sem_ptr) call and returns (r, if r < 0 { Errno::last() } else { Errno::from_raw(0) }) to eliminate the duplicated closure in multiprocessing.rs while preserving VirtualMachine, sem_ptr, and Errno behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@crates/stdlib/src/multiprocessing.rs`:
- Around line 783-795: Extract the duplicated vm.allow_threads closure that
calls libc::sem_wait and captures errno into a helper function (e.g., fn
sem_wait_with_errno(vm: &VirtualMachine, sem_ptr: *mut sem_t) -> (libc::c_int,
Errno)) and replace both occurrences with let (r, e) = sem_wait_with_errno(vm,
sem_ptr); so the logic inside sem_wait_with_errno performs the unsafe
libc::sem_wait(sem_ptr) call and returns (r, if r < 0 { Errno::last() } else {
Errno::from_raw(0) }) to eliminate the duplicated closure in multiprocessing.rs
while preserving VirtualMachine, sem_ptr, and Errno behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 2bf61cbb-6a55-4009-b155-70cbf3eb6c08
📒 Files selected for processing (2)
crates/stdlib/src/multiprocessing.rscrates/vm/src/builtins/tuple.rs
✅ Files skipped from review due to trivial changes (1)
- crates/vm/src/builtins/tuple.rs
allow_threads may call attach_thread() on return, which can invoke syscalls that clobber errno. Capture errno inside the closure before it is lost.
8ec74ef to
a47c97a
Compare
allow_threads may call attach_thread() on return, which can invoke syscalls that clobber errno. Capture errno inside the closure before it is lost.
Summary by CodeRabbit
Bug Fixes
Refactor