Add more error functions to the c-api#8248
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe C-API now exposes VM-backed exception state operations, platform error constructors, Unicode error accessors, traceback handling, signal utilities, and FFI error conversion. ChangesException and error C-API
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant CAPI
participant VM
participant Exception
CAPI->>VM: fetch, restore, or update exception state
VM->>Exception: normalize traceback and exception values
Exception-->>VM: exception attributes and triple
VM-->>CAPI: return pointers or FFI error sentinel
Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ 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/capi/src/pyerrors/errno.rs (1)
18-56: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReduce duplication by delegating to the object-based helper.
PyErr_SetFromErrnoWithFilenamere-implements the errno read,EINTRhandling, message construction, downcast, and call logic that already exists inPyErr_SetFromErrnoWithFilenameObjects. As in CPython, this can decode the filename and then delegate toPyErr_SetFromErrnoWithFilenameObject, keeping the errno/message logic in one place.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/capi/src/pyerrors/errno.rs` around lines 18 - 56, Refactor PyErr_SetFromErrnoWithFilename to only decode the optional C filename, convert it to a Python object, and delegate to PyErr_SetFromErrnoWithFilenameObject. Remove its duplicated errno retrieval, EINTR handling, message construction, exception downcast, and call logic so the object-based helper remains the single implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/capi/src/pyerrors/windows.rs`:
- Around line 69-84: In the Windows error conversion branch, avoid leaking the
decoded filename created by decode_fsdefault_and_size. Update the
Some(Ok(filename)) handling to keep the PyObjectRef alive locally and pass its
borrowed raw pointer to set_windows_error, rather than calling into_raw();
preserve the existing error and None handling.
---
Nitpick comments:
In `@crates/capi/src/pyerrors/errno.rs`:
- Around line 18-56: Refactor PyErr_SetFromErrnoWithFilename to only decode the
optional C filename, convert it to a Python object, and delegate to
PyErr_SetFromErrnoWithFilenameObject. Remove its duplicated errno retrieval,
EINTR handling, message construction, exception downcast, and call logic so the
object-based helper remains the single implementation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 05c2152b-5010-4ab6-a5ca-c0afe9842760
📒 Files selected for processing (5)
crates/capi/src/pyerrors.rscrates/capi/src/pyerrors/errno.rscrates/capi/src/pyerrors/unicode.rscrates/capi/src/pyerrors/windows.rscrates/capi/src/util.rs
8f6e3ec to
29f68a9
Compare
|
@coderabbitai resume |
✅ Action performedReviews resumed. |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/capi/src/pyerrors/errno.rs (1)
23-34: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winHandle
EINTRbefore decoding the filename. Match thePyErr_SetFromErrnoWithFilenameObjectsordering here: checkEINTRimmediately after readingerrno, beforedecode_fsdefault_and_size(...). Otherwise a decode failure can bypassvm.check_signals()and return the wrong exception.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/capi/src/pyerrors/errno.rs` around lines 23 - 34, Move the errno == libc::EINTR handling immediately after retrieving errno in the PyErr_SetFromErrnoWithFilenameObjects flow, before any filename null check or decode_fsdefault_and_size call. Preserve vm.check_signals()? behavior, then decode the filename only after signal handling completes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@crates/capi/src/pyerrors/errno.rs`:
- Around line 23-34: Move the errno == libc::EINTR handling immediately after
retrieving errno in the PyErr_SetFromErrnoWithFilenameObjects flow, before any
filename null check or decode_fsdefault_and_size call. Preserve
vm.check_signals()? behavior, then decode the filename only after signal
handling completes.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 415416af-d06c-4cb0-bcad-3eb97d1d62a2
📒 Files selected for processing (2)
crates/capi/src/pyerrors/errno.rscrates/capi/src/pyerrors/windows.rs
🚧 Files skipped from review as they are similar to previous changes (1)
- crates/capi/src/pyerrors/windows.rs
7c47ed9 to
1fdf316
Compare
Add windows error functions Implement unicode error functions Add errno functions to c-api Spell Review Refactor windows errors Review
1fdf316 to
dbfcbc8
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/capi/src/pyerrors.rs`:
- Around line 545-555: Update the PyErr_SetExcInfo handling around exc_val and
vm.set_exception so Py_None is treated the same as NULL, producing an empty
handled-exception state instead of being downcast as PyBaseException. Preserve
the existing TypeError for non-None values that are not exception instances, and
keep valid exception restoration unchanged.
- Around line 481-486: Update PyErr_GetHandledException and PyErr_GetExcInfo to
use topmost_exception() instead of current_exception(), so both APIs find the
oldest active handled exception past empty stack slots. Preserve
PyErr_GetExcInfo’s existing behavior of writing NULL values when no exception is
active; apply the changes at crates/capi/src/pyerrors.rs lines 481-486 and
507-535.
- Around line 490-497: Update PyErr_SetHandledException in
crates/capi/src/pyerrors.rs lines 490-497 to retain the incoming exception
rather than consume the raw pointer, while clearing handled-exception state for
NULL or Py_None. In the corresponding handled-exception setter at
crates/capi/src/pyerrors.rs lines 545-555, continue stealing type and traceback,
but treat value == NULL or Py_None as an empty handled state instead of
downcasting it.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 16ddb047-c75b-4bd8-b995-5381c46e5117
📒 Files selected for processing (5)
crates/capi/src/pyerrors.rscrates/capi/src/pyerrors/errno.rscrates/capi/src/pyerrors/unicode.rscrates/capi/src/pyerrors/windows.rscrates/capi/src/util.rs
🚧 Files skipped from review as they are similar to previous changes (4)
- crates/capi/src/util.rs
- crates/capi/src/pyerrors/windows.rs
- crates/capi/src/pyerrors/errno.rs
- crates/capi/src/pyerrors/unicode.rs
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
crates/capi/src/pyerrors.rs (1)
508-535: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winFix memory leaks when out-pointers are
NULL.When
ptype,pvalue, orptracebackis passed asNULL, the correspondingPyObjectRefreferences obtained fromvm.split_exception()are converted to raw pointers viainto_raw().as_ptr()but never written out or decremented. This causes the objects to leak because their reference counts are never decremented.Keep the references as
Option<PyObjectRef>until they are actually written to the non-NULLdestination pointers. This ensures that any discarded references automatically decrement their reference counts when the options are dropped at the end of the block.🐛 Proposed fix
- let (ty, value, tb) = vm.topmost_exception().map_or_else( - || { - ( - core::ptr::null_mut(), - core::ptr::null_mut(), - core::ptr::null_mut(), - ) - }, - |exc| { - let (ty, value, tb) = vm.split_exception(exc); - let tb = if vm.is_none(&tb) { - core::ptr::null_mut() - } else { - tb.into_raw().as_ptr() - }; - (ty.into_raw().as_ptr(), value.into_raw().as_ptr(), tb) - }, - ); - - if let Some(ptype) = NonNull::new(ptype) { - unsafe { ptype.write(ty) }; - } - if let Some(pvalue) = NonNull::new(pvalue) { - unsafe { pvalue.write(value) }; - } - if let Some(ptraceback) = NonNull::new(ptraceback) { - unsafe { ptraceback.write(tb) }; - } + let (ty, value, tb) = vm.topmost_exception().map_or_else( + || (None, None, None), + |exc| { + let (ty, value, tb) = vm.split_exception(exc); + let tb = if vm.is_none(&tb) { None } else { Some(tb) }; + (Some(ty), Some(value), tb) + }, + ); + + if let Some(ptype) = NonNull::new(ptype) { + unsafe { ptype.write(ty.map_or(core::ptr::null_mut(), |x| x.into_raw().as_ptr())) }; + } + if let Some(pvalue) = NonNull::new(pvalue) { + unsafe { pvalue.write(value.map_or(core::ptr::null_mut(), |x| x.into_raw().as_ptr())) }; + } + if let Some(ptraceback) = NonNull::new(ptraceback) { + unsafe { ptraceback.write(tb.map_or(core::ptr::null_mut(), |x| x.into_raw().as_ptr())) }; + }Note: Please ensure
PyErr_Fetch(around line 416) is also updated if it uses the same pattern of callinginto_raw()before checking forNULLpointers, as this would result in identical memory leaks.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/capi/src/pyerrors.rs` around lines 508 - 535, Update the exception-fetching logic around vm.split_exception and PyErr_Fetch to retain each extracted PyObjectRef as an Option until its corresponding out-pointer is validated; only call into_raw when ptype, pvalue, or ptraceback is non-NULL, allowing unconsumed references to drop and decrement their counts.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@crates/capi/src/pyerrors.rs`:
- Around line 508-535: Update the exception-fetching logic around
vm.split_exception and PyErr_Fetch to retain each extracted PyObjectRef as an
Option until its corresponding out-pointer is validated; only call into_raw when
ptype, pvalue, or ptraceback is non-NULL, allowing unconsumed references to drop
and decrement their counts.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 366486ed-8a81-4a52-b219-d5ab3beef433
📒 Files selected for processing (2)
crates/capi/src/pyerrors.rscrates/vm/src/vm/mod.rs
122fd5a to
46f2c23
Compare
Summary by CodeRabbit
exc_info, and interrupt/signal helpers.errnoand Windows error codes, with optional filename context.