From 232c538393134bb92816b88d686a73bda93f9a48 Mon Sep 17 00:00:00 2001 From: Charles Brossollet Date: Thu, 21 Nov 2019 15:15:50 +0100 Subject: [PATCH 1/4] Add FAQ entry, with code example, for dealing with long functions interruption --- docs/faq.rst | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/faq.rst b/docs/faq.rst index 93ccf10e57..9a6ea11bf6 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -248,6 +248,34 @@ that that were ``malloc()``-ed in another shared library, using data structures with incompatible ABIs, and so on. pybind11 is very careful not to make these types of mistakes. +How can I properly handle Ctrl-C in long-running functions? +=========================================================== + +Ctrl-C is received by the Python interpreter, and holds it until the GIL +is released, so a long-running function won't be interrupted. + +To interrupt from inside your function, you can use the ``PyErr_CheckSignals()`` function, +that will tell if a signal has been raised on the Python side. +It's a flag check so its impact is negligible. If a signal is on, interrupt execution by +throwing an exception that gets translated to KeyboardInterrupt +(see :doc:`advanced/exceptions` section): + +.. code-block:: cpp + + PYBIND11_MODULE(example, m) + { + m.def("long running_func", []() + { + for (;;) + { + if (PyErr_CheckSignals() != 0) + throw interruption_error(); + // Long running iteration + } + }); + py::register_exception(m, "KeyboardInterrupt"); + } + Inconsistent detection of Python version in CMake and pybind11 ============================================================== From 6eb81b7bcad4bcbd30efc74808102382c4972608 Mon Sep 17 00:00:00 2001 From: Charles Brossollet Date: Thu, 21 Nov 2019 16:29:25 +0100 Subject: [PATCH 2/4] Fix check-style error --- docs/faq.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index 9a6ea11bf6..e3e153a4b0 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -266,8 +266,7 @@ throwing an exception that gets translated to KeyboardInterrupt { m.def("long running_func", []() { - for (;;) - { + for (;;) { if (PyErr_CheckSignals() != 0) throw interruption_error(); // Long running iteration From 8500485211be8f5bb9190e9586889bb342d29b3c Mon Sep 17 00:00:00 2001 From: Charles Brossollet Date: Fri, 22 Nov 2019 09:43:35 +0100 Subject: [PATCH 3/4] Add interruption error --- docs/faq.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/faq.rst b/docs/faq.rst index e3e153a4b0..11eda55b1e 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -262,6 +262,13 @@ throwing an exception that gets translated to KeyboardInterrupt .. code-block:: cpp + class interruption_error: public std::exception { + public: + const char* what() const noexcept{ + return "Interruption signal caught."; + } + }; + PYBIND11_MODULE(example, m) { m.def("long running_func", []() From 58074c18b6dbd6d5e7716ae4544c617cab8c3cc0 Mon Sep 17 00:00:00 2001 From: Charles Brossollet Date: Mon, 25 Nov 2019 08:49:30 +0100 Subject: [PATCH 4/4] rewording, and brace space --- docs/faq.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index 11eda55b1e..a7cbbfdf45 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -254,17 +254,18 @@ How can I properly handle Ctrl-C in long-running functions? Ctrl-C is received by the Python interpreter, and holds it until the GIL is released, so a long-running function won't be interrupted. -To interrupt from inside your function, you can use the ``PyErr_CheckSignals()`` function, -that will tell if a signal has been raised on the Python side. -It's a flag check so its impact is negligible. If a signal is on, interrupt execution by -throwing an exception that gets translated to KeyboardInterrupt -(see :doc:`advanced/exceptions` section): +To interrupt from inside your function, you can use the ``PyErr_CheckSignals()`` +function, that will tell if a signal has been raised on the Python side. This +function merely checks a flag, so its impact is negligible. When a signal has +been received, you can explicitely interrupt execution by throwing an exception +that gets translated to KeyboardInterrupt (see :doc:`advanced/exceptions` +section): .. code-block:: cpp class interruption_error: public std::exception { public: - const char* what() const noexcept{ + const char* what() const noexcept { return "Interruption signal caught."; } };