From 4d008218a0a58897bc5a6504a84b9eb2ffb4b591 Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Wed, 7 Oct 2020 19:14:37 +0200 Subject: [PATCH] Add wrapper for PyErr_CheckSignals() to Python. This is a useful API in long-running Rust code, which lets users cancel evaluation by pressing Ctrl-C, and run any other signal handlers that have been set using the signal module. --- CHANGELOG.md | 1 + src/python.rs | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf23660b..cfb10e88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ## Added - Add support for keyword-only arguments without default values in `#[pyfunction]`. [#1209](https://github.com/PyO3/pyo3/pull/1209) +- Add a wrapper for `PyErr_CheckSignals()` as `Python::check_signals()`. [#1214](https://github.com/PyO3/pyo3/pull/1214) ## [0.12.1] - 2020-09-16 ### Fixed diff --git a/src/python.rs b/src/python.rs index 88c372b8..bdd15bab 100644 --- a/src/python.rs +++ b/src/python.rs @@ -498,6 +498,26 @@ impl<'p> Python<'p> { pub fn xdecref(self, ptr: T) { unsafe { ffi::Py_XDECREF(ptr.into_ptr()) }; } + + /// Lets the Python interpreter check for pending signals and invoke the + /// corresponding signal handlers. This can run arbitrary Python code. + /// + /// If an exception is raised by the signal handler, or the default signal + /// handler raises an exception (such as `KeyboardInterrupt` for `SIGINT`), + /// an `Err` is returned. + /// + /// This is a wrapper of the C function `PyErr_CheckSignals()`. It is good + /// practice to call this regularly in a long-running calculation since + /// SIGINT and other signals handled by Python code are left pending for its + /// entire duration. + pub fn check_signals(self) -> PyResult<()> { + let v = unsafe { ffi::PyErr_CheckSignals() }; + if v == -1 { + Err(PyErr::fetch(self)) + } else { + Ok(()) + } + } } #[cfg(test)]