Repository: Pyomo/pyomo

Issue:
Signal handling cannot be fully disabled from Pyomo
PyUtilib introduced a global flag to disable signal handling to make it possible to run in a child thread: https://github.com/PyUtilib/pyutilib/issues/31.

Pyomo introduced the ability to disable signal handling from within Pyomo with this commit: https://github.com/Pyomo/pyomo/commit/56a0ad0087505542b49b231cb302764662a9c377#diff-dc8d07ca749659ddf79ddce63a487577.  Pyomo's use_signal_handling flag must now
be set to False; otherwise Pyomo overwrites the pyutilib.subprocess.GlobalData.DEFINE_SIGNAL_HANDLERS_DEFAULT with its default True when solving (line 446-447 in pyutilib/pyutilib/subprocess/processmngr.py, i.e. the global value is used only if no value is passed).

Even if the Pyomo use_signal_handling_flag is set to False, however, setting pyutilib.subprocess.GlobalData.DEFINE_SIGNAL_HANDLERS_DEFAULT to False is still needed because Pyomo passes the use_signal_handling_flag only in pyomo/opt/solver/shellcmd.py but calls pyutilib.processmngr.run several times before getting to that point, e.g. in pyomo/solvers/plugins/solvers/CBCplugin.py. So if the PyUtilib global flag is not set to False, the 'signal only works in main thread' error is raised in CBCplugin.py. So fully disabling signal handling currently (Pyomo 5.6.2 and PyUtilib 5.7.0) requires setting both PyUtilib's DEFINE_SIGNAL_HANDLERS_DEFAULT and Pyomo's use_signal_handling flags to False, which is confusing and can take a while to track down.

Please consider passing the use_signal_handling_flag everywhere it is required,
so that signal handling can be disabled fully from Pyomo.

Signal handling cannot be fully disabled from Pyomo
PyUtilib introduced a global flag to disable signal handling to make it possible to run in a child thread: https://github.com/PyUtilib/pyutilib/issues/31.

Pyomo introduced the ability to disable signal handling from within Pyomo with this commit: https://github.com/Pyomo/pyomo/commit/56a0ad0087505542b49b231cb302764662a9c377#diff-dc8d07ca749659ddf79ddce63a487577.  Pyomo's use_signal_handling flag must now
be set to False; otherwise Pyomo overwrites the pyutilib.subprocess.GlobalData.DEFINE_SIGNAL_HANDLERS_DEFAULT with its default True when solving (line 446-447 in pyutilib/pyutilib/subprocess/processmngr.py, i.e. the global value is used only if no value is passed).

Even if the Pyomo use_signal_handling_flag is set to False, however, setting pyutilib.subprocess.GlobalData.DEFINE_SIGNAL_HANDLERS_DEFAULT to False is still needed because Pyomo passes the use_signal_handling_flag only in pyomo/opt/solver/shellcmd.py but calls pyutilib.processmngr.run several times before getting to that point, e.g. in pyomo/solvers/plugins/solvers/CBCplugin.py. So if the PyUtilib global flag is not set to False, the 'signal only works in main thread' error is raised in CBCplugin.py. So fully disabling signal handling currently (Pyomo 5.6.2 and PyUtilib 5.7.0) requires setting both PyUtilib's DEFINE_SIGNAL_HANDLERS_DEFAULT and Pyomo's use_signal_handling flags to False, which is confusing and can take a while to track down.

Please consider passing the use_signal_handling_flag everywhere it is required,
so that signal handling can be disabled fully from Pyomo.



Discussion:

Resolving patch:
diff --git a/pyomo/opt/solver/shellcmd.py b/pyomo/opt/solver/shellcmd.py
--- a/pyomo/opt/solver/shellcmd.py
+++ b/pyomo/opt/solver/shellcmd.py
@@ -46,7 +46,7 @@ def __init__(self, **kwargs):
         # broadly useful for reporting, and in cases where
         # a solver plugin may not report execution time.
         self._last_solve_time = None
-        self._define_signal_handlers = True
+        self._define_signal_handlers = None
 
         if executable is not None:
             self.set_executable(name=executable, validate=validate)
@@ -193,7 +193,7 @@ def _presolve(self, *args, **kwds):
         TempfileManager.push()
 
         self._keepfiles = kwds.pop("keepfiles", False)
-        self._define_signal_handlers = kwds.pop('use_signal_handling',True)
+        self._define_signal_handlers = kwds.pop('use_signal_handling',None)
 
         OptSolver._presolve(self, *args, **kwds)
 


Test patch: