From 2b583e7a57b94d97e128a2b8b4f8ff303db08cd9 Mon Sep 17 00:00:00 2001 From: Sasha Rahlin Date: Mon, 1 Apr 2024 18:47:39 -0500 Subject: [PATCH] Optionally disable pipeline halt on SIGINT Optional argument `signal_halt` for the `G3Pipeline.Run()` method. By default, this is set to True to enable current behavior, namely that a pipeline is halted (via the `halt_processing` flag) and terminates after the the current frame reaches the end of the pipeline. If False, this signal handling is disabled, and it is then up to the user to ensure that a running pipeline is properly halted on interrupt. --- core/include/core/G3Pipeline.h | 2 +- core/src/G3Pipeline.cxx | 19 +++++++++++-------- core/src/python.cxx | 11 +++++++---- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/core/include/core/G3Pipeline.h b/core/include/core/G3Pipeline.h index 539f97a7..7bcfbf4a 100644 --- a/core/include/core/G3Pipeline.h +++ b/core/include/core/G3Pipeline.h @@ -32,7 +32,7 @@ class G3Pipeline { // Run the pipeline to completion. If profile is set to true, will print // statistics for each module at completion. - void Run(bool profile = false, bool graph = false); + void Run(bool profile = false, bool graph = false, bool signal_halt = true); // If there is stored graph information get it std::string GetGraphInfo() const { diff --git a/core/src/G3Pipeline.cxx b/core/src/G3Pipeline.cxx index 0756984d..13ceecfc 100644 --- a/core/src/G3Pipeline.cxx +++ b/core/src/G3Pipeline.cxx @@ -212,7 +212,7 @@ G3Pipeline::siginfo_catcher(int) #endif void -G3Pipeline::Run(bool profile, bool graph) +G3Pipeline::Run(bool profile, bool graph, bool signal_halt) { struct rusage last_rusage; std::vector mods; @@ -239,12 +239,14 @@ G3Pipeline::Run(bool profile, bool graph) getrusage(RUSAGE_THREAD, &last_rusage); #endif - // Catch SIGINT - sigint_catcher.sa_handler = &G3Pipeline::sigint_catcher; - sigint_catcher.sa_flags = SA_RESTART | SA_RESETHAND; - sigemptyset(&sigint_catcher.sa_mask); - sigaddset(&sigint_catcher.sa_mask, SIGINT); - sigaction(SIGINT, &sigint_catcher, &oldsigint); + if (signal_halt) { + // Catch SIGINT + sigint_catcher.sa_handler = &G3Pipeline::sigint_catcher; + sigint_catcher.sa_flags = SA_RESTART | SA_RESETHAND; + sigemptyset(&sigint_catcher.sa_mask); + sigaddset(&sigint_catcher.sa_mask, SIGINT); + sigaction(SIGINT, &sigint_catcher, &oldsigint); + } #ifdef SIGINFO if (profile) { @@ -288,7 +290,8 @@ G3Pipeline::Run(bool profile, bool graph) // Restore old handler G3Pipeline::halt_processing = false; - sigaction(SIGINT, &oldsigint, &sigint_catcher); + if (signal_halt) + sigaction(SIGINT, &oldsigint, &sigint_catcher); #ifdef SIGINFO if (profile) sigaction(SIGINFO, &oldsiginfo, &siginfo_catcher); diff --git a/core/src/python.cxx b/core/src/python.cxx index 71f63f94..2897652c 100644 --- a/core/src/python.cxx +++ b/core/src/python.cxx @@ -578,17 +578,20 @@ SPT3G_PYTHON_MODULE(core) "\t processing if returned by first module. Equivalent to [].\n") .def("_Add_", &G3Pipeline::Add, bp::arg("name")="") .def("Run", &G3Pipeline::Run, - (bp::arg("profile")=false, bp::arg("graph")=false), + (bp::arg("profile")=false, bp::arg("graph")=false, + bp::arg("signal_halt")=true), "Run pipeline. If profile is True, print execution time " "statistics for each module when complete. If graph is True, " "stores control flow data that can be processed with GraphViz " - "once retrieved using GetGraphInfo().") + "once retrieved using GetGraphInfo(). If signal_halt is True " + "(default), the pipeline will stop processing new frames when " + "SIGINT is sent to this process. Equivalent to what happens when " + "halt_processing() is called.") .def("GetGraphInfo", &G3Pipeline::GetGraphInfo, "Get stored control flow information from Run(graph=True)") .def("halt_processing", &G3Pipeline_halt_processing, "Halts all running pipelines after they flush all currently " - "in-flight frames. Equivalent to what happens when SIGINT is " - "sent to this process. Once set, the first module will not be " + "in-flight frames. Once set, the first module will not be " "called again.") .staticmethod("halt_processing") .def_readonly("last_frame",