When using e.g. rosbag record in a process with no signal handler installed, or signal handlers of type SIG_IGN, SIG_DFL, rosbag_main.py will throw TypeError: 'Handlers' object is not callable :
Traceback (most recent call last):
File "/opt/ros/noetic/bin/rosbag", line 35, in <module>
rosbag.rosbagmain()
File "/opt/ros/noetic/lib/python3/dist-packages/rosbag/rosbag_main.py", line 1032, in rosbagmain
cmds[cmd](argv[2:])
File "/opt/ros/noetic/lib/python3/dist-packages/rosbag/rosbag_main.py", line 161, in record_cmd
process.wait()
File "/usr/lib/python3.6/subprocess.py", line 1477, in wait
(pid, sts) = self._try_wait(0)
File "/usr/lib/python3.6/subprocess.py", line 1424, in _try_wait
(pid, sts) = os.waitpid(self.pid, wait_flags)
File "/opt/ros/noetic/lib/python3/dist-packages/rosbag/rosbag_main.py", line 155, in <lambda>
lambda signum, frame: _send_process_sigint(signum, frame, old_handler, process)
File "/opt/ros/noetic/lib/python3/dist-packages/rosbag/rosbag_main.py", line 78, in _send_process_sigint
old_handler(signum, frame)
TypeError: 'Handlers' object is not callable
Explanation:
The following snippets in rosbag_main.py assume that old_handler is callable, and therefore throw the error if this is not the case.
old_handler is set by calling signal.signal(), which returns either a callable function or a non-callable special value of either signal.SIG_IGN, signal.SIG_DFL or None. However, only for the case where the handler is None is protected.
Issue:
When using e.g.
rosbag record
in a process with no signal handler installed, or signal handlers of typeSIG_IGN
,SIG_DFL
, rosbag_main.py will throwTypeError: 'Handlers' object is not callable
:Explanation:
The following snippets in rosbag_main.py assume that
old_handler
is callable, and therefore throw the error if this is not the case.https://github.com/ros/ros_comm/blob/3f8eca4a1f13996b33c03a5c4ee3a69fb0db3668/tools/rosbag/src/rosbag/rosbag_main.py#L69-L72 https://github.com/ros/ros_comm/blob/3f8eca4a1f13996b33c03a5c4ee3a69fb0db3668/tools/rosbag/src/rosbag/rosbag_main.py#L75-L78
old_handler
is set by calling signal.signal(), which returns either a callable function or a non-callable special value of eithersignal.SIG_IGN
,signal.SIG_DFL
orNone
. However, only for the case where the handler isNone
is protected.https://python.readthedocs.io/en/latest/library/signal.html#signal.signal
Minimal example
Running this script and then killing the spawned python3 process with
kill -s INT [PID]
will throw the error. The ampersand will make the process inheritSIG_IGN
settings forSIGINT
andSIGQUIT
.Possible solution
To avoid calling a non-callable object, replace lines https://github.com/ros/ros_comm/blob/3f8eca4a1f13996b33c03a5c4ee3a69fb0db3668/tools/rosbag/src/rosbag/rosbag_main.py#L71 https://github.com/ros/ros_comm/blob/3f8eca4a1f13996b33c03a5c4ee3a69fb0db3668/tools/rosbag/src/rosbag/rosbag_main.py#L77
with
if callable(old_handler):
Similar issue in python-socketio: https://github.com/miguelgrinberg/python-socketio/issues/517