-
Notifications
You must be signed in to change notification settings - Fork 139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Launch system hungs while shutdown #90
Comments
For me this seems to be with any launch file while using fastrtps (even if they don't involve lifecycle nodes). For example, |
@ironmig On
|
Yes this is on x86 Ubuntu 18.04 running off the latest master branch |
@sumanth-nirmal I have some answers for you:
That is because we never unregister the event handler (as we spoke about in person). To remedy this, I will:
As for why it hangs, well, that's a more serious flaw in my design, essentially the
Unfortunately, I'll have to fix these after the release of Bouncy. In the meantime, you can use the |
Here's a modified version of your script that does not react to talker reaching from launch import LaunchDescription
import launch
import launch.actions
import launch.events
import launch_ros.actions
import launch_ros.events
import launch_ros.events.lifecycle
import lifecycle_msgs.msg
def generate_launch_description():
lifecycle_talker = launch_ros.actions.LifecycleNode(
node_name='talker', package='lifecycle', node_executable='lifecycle_talker', output='screen')
lifecycle_listener_factory = launch.actions.OpaqueFunction(function=lambda context: [
launch_ros.actions.LifecycleNode(
node_name='listener', package='lifecycle', node_executable='lifecycle_listener',
output='screen')
])
# When the talker reaches the 'inactive' state, make it take the 'activate' transition
def on_talker_reaches_inactive(context):
nonlocal on_talker_transitions_to_inactive_event_handler
# comment this line if you want a new listener everytime
context.unregister_event_handler(on_talker_transitions_to_inactive_event_handler)
return [
launch.actions.EmitEvent(event=launch_ros.events.lifecycle.ChangeState(
lifecycle_node_matcher=launch.events.process.matches_action(lifecycle_talker),
transition_id=lifecycle_msgs.msg.Transition.TRANSITION_ACTIVATE,
)),
]
on_talker_transitions_to_inactive_event_handler = launch_ros.event_handlers.OnStateTransition(
target_lifecycle_node=lifecycle_talker, goal_state='inactive',
entities=[
launch.actions.LogInfo(
msg="node 'talker' reached the 'inactive' state, 'activating'."),
launch.actions.OpaqueFunction(function=on_talker_reaches_inactive),
],
)
register_event_handler_for_talker_reaches_inactive_state = launch.actions.RegisterEventHandler(
on_talker_transitions_to_inactive_event_handler
)
# When the talker node reaches the 'active' state, log a message and start the listener node.
register_event_handler_for_talker_reaches_active_state = launch.actions.RegisterEventHandler(
launch_ros.event_handlers.OnStateTransition(
target_lifecycle_node=lifecycle_talker, goal_state='active',
entities=[
launch.actions.LogInfo(
msg="node 'talker' reached the 'active' state, launching 'listener'."),
lifecycle_listener_factory,
],
)
)
# Make the talker node take the 'configure' transition.
emit_event_to_request_that_talker_does_configure_transition = launch.actions.EmitEvent(
event=launch_ros.events.lifecycle.ChangeState(
lifecycle_node_matcher=launch.events.process.matches_action(lifecycle_talker),
transition_id=lifecycle_msgs.msg.Transition.TRANSITION_CONFIGURE,
)
)
"""Launch a talker and a listener."""
return LaunchDescription([
register_event_handler_for_talker_reaches_inactive_state,
register_event_handler_for_talker_reaches_active_state,
lifecycle_talker,
emit_event_to_request_that_talker_does_configure_transition
]) If you comment out Here it is as a diff: --- from launch import LaunchDescription
+++ (clipboard)
@@ -8,26 +8,39 @@
import lifecycle_msgs.msg
+
def generate_launch_description():
lifecycle_talker = launch_ros.actions.LifecycleNode(
- node_name = 'talker', package='lifecycle', node_executable='lifecycle_talker', output='screen')
+ node_name='talker', package='lifecycle', node_executable='lifecycle_talker', output='screen')
- lifecycle_listener = launch_ros.actions.LifecycleNode(
- node_name='listener', package='lifecycle', node_executable='lifecycle_listener', output='screen')
+ lifecycle_listener_factory = launch.actions.OpaqueFunction(function=lambda context: [
+ launch_ros.actions.LifecycleNode(
+ node_name='listener', package='lifecycle', node_executable='lifecycle_listener',
+ output='screen')
+ ])
# When the talker reaches the 'inactive' state, make it take the 'activate' transition
+ def on_talker_reaches_inactive(context):
+ nonlocal on_talker_transitions_to_inactive_event_handler
+ # comment this line if you want a new listener everytime
+ # context.unregister_event_handler(on_talker_transitions_to_inactive_event_handler)
+ return [
+ launch.actions.EmitEvent(event=launch_ros.events.lifecycle.ChangeState(
+ lifecycle_node_matcher=launch.events.process.matches_action(lifecycle_talker),
+ transition_id=lifecycle_msgs.msg.Transition.TRANSITION_ACTIVATE,
+ )),
+ ]
+
+ on_talker_transitions_to_inactive_event_handler = launch_ros.event_handlers.OnStateTransition(
+ target_lifecycle_node=lifecycle_talker, goal_state='inactive',
+ entities=[
+ launch.actions.LogInfo(
+ msg="node 'talker' reached the 'inactive' state, 'activating'."),
+ launch.actions.OpaqueFunction(function=on_talker_reaches_inactive),
+ ],
+ )
register_event_handler_for_talker_reaches_inactive_state = launch.actions.RegisterEventHandler(
- launch_ros.event_handlers.OnStateTransition(
- target_lifecycle_node=lifecycle_talker, goal_state='inactive',
- entities=[
- launch.actions.LogInfo(
- msg="node 'talker' reached the 'inactive' state, 'activating'."),
- launch.actions.EmitEvent(event=launch_ros.events.lifecycle.ChangeState(
- lifecycle_node_matcher=launch.events.process.matches_action(lifecycle_talker),
- transition_id=lifecycle_msgs.msg.Transition.TRANSITION_ACTIVATE,
- )),
- ],
- )
+ on_talker_transitions_to_inactive_event_handler
)
# When the talker node reaches the 'active' state, log a message and start the listener node.
@@ -37,7 +50,7 @@
entities=[
launch.actions.LogInfo(
msg="node 'talker' reached the 'active' state, launching 'listener'."),
- lifecycle_listener,
+ lifecycle_listener_factory,
],
)
)
|
@wjwwood Thanks. I will use the modified script. |
I'm going to close this since I created follow up issues for the specific problems and there is a work around for @sumanth-nirmal right now. |
Bug report
Required Info:
Steps to reproduce issue
Launch system for 2 nodes (talker --> lifecycle node and listener --> regular node) with following actions:
Launch file is below:
Start the launch and when talker node is in Active state, trigger transition to Inactive with
Once the talker node is back in the Active state,
Ctrl-C
makes the launch to hung with the following error:Expected behavior
The launch system cleanly exit on
Ctrl-C
Actual behavior
The launch system hangs on
Ctrl-C
with the above launch fileAdditional information
Also every time the talker node reaches Active state it starts a new Listener node.
The text was updated successfully, but these errors were encountered: