fix: Flush stdout on shutdown matching CPython behavior#7503
Conversation
When stdout flush fails during shutdown, report the error via run_unraisable and exit with code 120 (matching CPython's Py_FinalizeEx). Skip flushing already-closed or None streams. Stderr flush errors remain silently ignored per CPython behavior. Fixes RustPython#5521 Signed-off-by: majiayu000 <1835304752@qq.com>
|
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 (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdded stdout/stderr flush-status tracking: Changes
Sequence Diagram(s)sequenceDiagram
participant Interpreter
participant VirtualMachine
participant StdStream as Stdout/Stderr
participant Unraisable as run_unraisable
Interpreter->>VirtualMachine: call flush_std()
VirtualMachine->>StdStream: check None/closed, call flush()
alt flush raises exception (stdout)
VirtualMachine->>Unraisable: run_unraisable(err, None, stdout)
VirtualMachine-->>Interpreter: return -1 (flush_status)
else flush succeeds or skipped
VirtualMachine-->>Interpreter: return 0 (flush_status)
end
Interpreter->>VirtualMachine: final flush_std() during shutdown
VirtualMachine->>StdStream: flush/skip as above
Interpreter->>Interpreter: if initial flush_status < 0 and exit_code == 0 set exit_code = 120
Note over Interpreter: exit with computed exit_code
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 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.
🧹 Nitpick comments (1)
crates/vm/src/vm/interpreter.rs (1)
446-448: Optional readability tweak: replace120with a named constant.A small constant (e.g.,
EXITCODE_FLUSH_STDERR_FAILURE/EXITCODE_FLUSH_FAILURE) would make this CPython-compat mapping easier to maintain.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/vm/src/vm/interpreter.rs` around lines 446 - 448, Replace the magic literal 120 with a named constant to improve readability and maintainability: define a top-level constant (e.g., EXITCODE_FLUSH_FAILURE: i32 = 120) in the same module and use it in the if branch that currently returns 120 (the code referencing exit_code and flush_status inside the interpreter logic), e.g., change the branch to return EXITCODE_FLUSH_FAILURE instead of the literal; ensure the constant name clearly indicates its purpose (CPython flush-failure exit code).
🤖 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/vm/src/vm/interpreter.rs`:
- Around line 446-448: Replace the magic literal 120 with a named constant to
improve readability and maintainability: define a top-level constant (e.g.,
EXITCODE_FLUSH_FAILURE: i32 = 120) in the same module and use it in the if
branch that currently returns 120 (the code referencing exit_code and
flush_status inside the interpreter logic), e.g., change the branch to return
EXITCODE_FLUSH_FAILURE instead of the literal; ensure the constant name clearly
indicates its purpose (CPython flush-failure exit code).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 22376891-c5a9-4eed-bd4e-c8ee576083ea
⛔ Files ignored due to path filters (1)
Lib/test/test_cmd_line.pyis excluded by!Lib/**
📒 Files selected for processing (2)
crates/vm/src/vm/interpreter.rscrates/vm/src/vm/vm_object.rs
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: [ ] test: cpython/Lib/test/test_cmd_line.py (TODO: 23) dependencies: dependent tests: (no tests depend on cmd_line) Legend:
|
…_FAILURE Address review feedback on PR RustPython#7503: improve readability by extracting the CPython-compat exit code into a named constant. Signed-off-by: majiayu000 <1835304752@qq.com>
arihant2math
left a comment
There was a problem hiding this comment.
This was what I was looking for, thanks. LGTM!
ShaharNaveh
left a comment
There was a problem hiding this comment.
lgtm!
ty, and welcome to the project:)
youknowone
left a comment
There was a problem hiding this comment.
Thank you so much! and welcome to Rustpython project
Fixes #5521
Summary
RustPython was not flushing stdout on interpreter shutdown, and when stdout flush failed (e.g. broken pipe), it silently ignored the error instead of returning exit code 120 like CPython does.
Changes:
vm_object.rs:flush_std()now returnsi32status (0 = ok, -1 = stdout flush failed). On stdout flush failure, callsrun_unraisable()to report the error to stderr. Addedfile_is_closed()helper to skip flushing already-closed files. Stderr flush errors remain silently ignored (matching CPython).interpreter.rs:finalize()tracks flush status. Ifexit_codeis 0 and stdout flush failed, returns 120 instead of 0. Non-zero exit codes (e.g. fromSystemExit) are preserved.test_cmd_line.py: Removed@unittest.expectedFailurefromtest_stdout_flush_at_shutdown.Test Plan
cargo test --workspace --features threadingpassescargo clippycleantest_stdout_flush_at_shutdownnow passes withoutexpectedFailureSummary by CodeRabbit