Skip to content

Commit 3ff6432

Browse files
authored
Merge branch 'master' into fix/disable/effort_limiting
2 parents 45599de + 5ffe21a commit 3ff6432

3 files changed

Lines changed: 32 additions & 5 deletions

File tree

controller_manager/controller_manager/spawner.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def parse_args_advanced(args):
108108
"-u",
109109
"--unload-on-kill",
110110
action="store_true",
111-
help="Deactivate the active controllers and unload them on kill",
111+
help="Deactivate the active controllers and unload them on SIGINT or SIGTERM",
112112
)
113113
global_parser.add_argument("-h", "--help", action="store_true", help="Show help")
114114

@@ -239,7 +239,7 @@ def parse_native_args(args):
239239
parser.add_argument(
240240
"-u",
241241
"--unload-on-kill",
242-
help="Wait until this application is interrupted and unload controller",
242+
help="Wait until this application is interrupted (SIGINT or SIGTERM) and deactivate/unload controllers",
243243
action="store_true",
244244
)
245245
parser.add_argument(
@@ -358,6 +358,13 @@ def get_ros_params_files(argv):
358358
activate_as_group = global_args.activate_as_group
359359
unload_on_kill = global_args.unload_on_kill
360360
node = None
361+
lock = None
362+
363+
def _on_shutdown_signal(signum, frame):
364+
raise KeyboardInterrupt()
365+
366+
signal.signal(signal.SIGINT, _on_shutdown_signal)
367+
signal.signal(signal.SIGTERM, _on_shutdown_signal)
361368

362369
if spawner_ros_params_files:
363370
for controller in controllers:
@@ -574,6 +581,7 @@ def get_ros_params_files(argv):
574581
# second KeyboardInterrupt during the signal.signal() call itself.
575582
try:
576583
signal.signal(signal.SIGINT, signal.SIG_IGN)
584+
signal.signal(signal.SIGTERM, signal.SIG_IGN)
577585
except (KeyboardInterrupt, Exception):
578586
pass
579587
if unload_on_kill:
@@ -632,7 +640,7 @@ def get_ros_params_files(argv):
632640
finally:
633641
if node:
634642
node.destroy_node()
635-
if lock.is_locked:
643+
if lock is not None and lock.is_locked:
636644
lock.release()
637645
rclpy.shutdown()
638646

controller_manager/doc/userdoc.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ There are two scripts to interact with controller manager from launch files:
182182
Controller param file to be loaded into controller node before configure. Pass multiple times to load different files for different controllers or to override the parameters of the same controller.
183183
--load-only Only load the controller and leave unconfigured.
184184
--inactive Load and configure the controller, however do not activate them
185-
-u, --unload-on-kill Wait until this application is interrupted and unload controller
185+
-u, --unload-on-kill Wait until this application is interrupted (SIGINT or SIGTERM) and deactivate/unload controllers
186186
--controller-manager-timeout CONTROLLER_MANAGER_TIMEOUT
187187
Time to wait for the controller manager service to be available
188188
--switch-timeout SWITCH_TIMEOUT
@@ -267,7 +267,7 @@ The ``spawner`` now supports per controller arguments, while parsing the argumen
267267
--activate-as-group Activate controllers as a group
268268
--switch-asap, --no-switch-asap
269269
Switch controllers as soon as possible
270-
-u, --unload-on-kill Deactivate the active controllers and unload them on kill
270+
-u, --unload-on-kill Deactivate the active controllers and unload them on SIGINT or SIGTERM
271271
-h, --help Show help
272272
273273
Controller Options:

controller_manager/test/test_spawner_unspawner.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,25 @@ TEST_F(TestLoadController, unload_on_kill_activate_as_group)
605605
ASSERT_EQ(cm_->get_loaded_controllers().size(), 0ul);
606606
}
607607

608+
TEST_F(TestLoadController, unload_on_kill_with_sigterm)
609+
{
610+
// When a launch file shuts down because a required sibling process crashes,
611+
// it sends SIGINT and escalates to SIGTERM, --unload-on-kill must still
612+
// deactivate and unload the controller when SIGTERM is delivered.
613+
ControllerManagerRunner cm_runner(this);
614+
cm_->set_parameter(rclcpp::Parameter("ctrl_3.type", test_controller::TEST_CONTROLLER_CLASS_NAME));
615+
std::stringstream ss;
616+
ss << "timeout --signal=TERM 5 "
617+
<< std::string(coveragepy_script) +
618+
" $(ros2 pkg prefix controller_manager)/lib/controller_manager/spawner "
619+
<< "ctrl_3 -c test_controller_manager --unload-on-kill";
620+
621+
EXPECT_NE(std::system(ss.str().c_str()), 0)
622+
<< "timeout should have killed spawner and returned non 0 code";
623+
624+
ASSERT_EQ(cm_->get_loaded_controllers().size(), 0ul);
625+
}
626+
608627
TEST_F(TestLoadController, spawner_test_to_check_parameter_overriding)
609628
{
610629
const std::string main_test_file_path =

0 commit comments

Comments
 (0)