Skip to content

Handle KeyboardInterrupt exception in also Windows #4452

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,5 @@ fn main() -> ExitCode {
vm.add_native_modules(rustpython_stdlib::get_module_inits());
});
let result = py_main(&interp);
ExitCode::from(interp.run(|_vm| result))
interp.run(|_vm| result)
}
2 changes: 1 addition & 1 deletion examples/package_embed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ fn main() -> ExitCode {
let result = result.map(|result| {
println!("name: {result}");
});
ExitCode::from(interp.run(|_vm| result))
interp.run(|_vm| result)
}
3 changes: 1 addition & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,8 @@ pub fn run(init: impl FnOnce(&mut VirtualMachine) + 'static) -> ExitCode {
config = config.init_hook(Box::new(init));

let interp = config.interpreter();
let exitcode = interp.run(move |vm| run_rustpython(vm, run_mode, quiet_var));

ExitCode::from(exitcode)
interp.run(move |vm| run_rustpython(vm, run_mode, quiet_var))
}

fn setup_main_module(vm: &VirtualMachine) -> PyResult<Scope> {
Expand Down
6 changes: 3 additions & 3 deletions vm/src/vm/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::{
stdlib::{atexit, sys},
PyResult,
};
use std::sync::atomic::Ordering;
use std::{process::ExitCode, sync::atomic::Ordering};

/// The general interface for the VM
///
Expand Down Expand Up @@ -59,7 +59,7 @@ impl Interpreter {
thread::enter_vm(&self.vm, || f(&self.vm))
}

pub fn run<F, R>(self, f: F) -> u8
pub fn run<F, R>(self, f: F) -> ExitCode
where
F: FnOnce(&VirtualMachine) -> PyResult<R>,
{
Expand All @@ -69,7 +69,7 @@ impl Interpreter {

// See if any exception leaked out:
let exit_code = res
.map(|_| 0)
.map(|_| ExitCode::from(0))
.map_err(|exc| vm.handle_exit_exception(exc))
.unwrap_or_else(|code| code);

Expand Down
26 changes: 16 additions & 10 deletions vm/src/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ use crate::{
AsObject, PyObject, PyObjectRef, PyPayload, PyRef, PyResult,
};
use crossbeam_utils::atomic::AtomicCell;
use std::sync::atomic::AtomicBool;
#[cfg(windows)]
use std::os::windows::process::ExitCodeExt;
use std::{
borrow::Cow,
cell::{Cell, Ref, RefCell},
collections::{HashMap, HashSet},
};
use std::{process::ExitCode, sync::atomic::AtomicBool};

pub use context::Context;
pub use interpreter::Interpreter;
Expand Down Expand Up @@ -732,19 +734,19 @@ impl VirtualMachine {
}
}

pub fn handle_exit_exception(&self, exc: PyBaseExceptionRef) -> u8 {
pub fn handle_exit_exception(&self, exc: PyBaseExceptionRef) -> ExitCode {
if exc.fast_isinstance(self.ctx.exceptions.system_exit) {
let args = exc.args();
let msg = match args.as_slice() {
[] => return 0,
[] => return ExitCode::from(0),
[arg] => match_class!(match arg {
ref i @ PyInt => {
use num_traits::cast::ToPrimitive;
return i.as_bigint().to_u8().unwrap_or(0);
return ExitCode::from(i.as_bigint().to_u8().unwrap_or(0));
}
arg => {
if self.is_none(arg) {
return 0;
return ExitCode::from(0);
} else {
arg.str(self).ok()
}
Expand All @@ -756,23 +758,27 @@ impl VirtualMachine {
let stderr = stdlib::sys::PyStderr(self);
writeln!(stderr, "{msg}");
}
1
ExitCode::from(1)
} else if exc.fast_isinstance(self.ctx.exceptions.keyboard_interrupt) {
#[allow(clippy::if_same_then_else)]
{
self.print_exception(exc);
#[cfg(unix)]
{
(libc::SIGINT as u8) + 128u8
ExitCode::from((libc::SIGINT as u8) + 128u8)
}
#[cfg(not(unix))]
#[cfg(windows)]
{
1
ExitCode::from_raw(winapi::um::winnt::STATUS_CONTROL_C_EXIT)
}
#[cfg(not(any(unix, windows)))]
{
ExitCode::from(1)
}
}
} else {
self.print_exception(exc);
1
ExitCode::from(1)
}
}

Expand Down