ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
1

Execute another process on process exit

asked 2021-04-20 16:04:01 -0500

Chuck Claunch gravatar image

I am attempting to use ROS2 launch to kick off a non-ROS-node executable (a long running process). This process is dirty and spawns other processes and needs a bit of clean up. I'm attempting to use the on_exit argument of the ExecuteProcess action to accomplish this and feed it another ExecuteProcess action which performs the necessary clean up. This second process executes properly if the first one ends on its own, but if I interrupt with CTRL-C it does not. Another action in the on_exit list (a LogInfo()) executes properly in both cases. It's strange to me that the log action executes but the process in the same list does not. Any thoughts would be greatly appreciated. Here's an example of what I'm doing. The long running process in this case is simply a shell sleep 5 and the second process is just an echo:

from launch import LaunchDescription
from launch.actions import ExecuteProcess, LogInfo


def generate_launch_description():
    """Launch the thing."""

    return LaunchDescription([
        ExecuteProcess(
            cmd=['sleep', '5'],
            log_cmd=True,
            on_exit=[
                ExecuteProcess(
                    cmd=['echo', 'it-worked!'],
                    log_cmd=True
                ),
                LogInfo(msg='This message prints properly.')
            ]
        )
    ])

And the output:

✔  20:54 ~ # ros2 launch test_package test_launch.py 
[INFO] [launch]: All log files can be found below /<redacted>
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [sleep-1]: process details: cmd=[sleep, 5], cwd='None', custom_env?=False
[INFO] [sleep-1]: process started with pid [16374]
[INFO] [sleep-1]: process has finished cleanly [pid 16374]
[INFO] [launch.user]: This message prints properly.
[INFO] [echo-2]: process details: cmd=[echo, it-worked!], cwd='None', custom_env?=False
[INFO] [echo-2]: process started with pid [16395]
[INFO] [echo-2]: process has finished cleanly [pid 16395]
✔  20:54 ~ # ros2 launch test_package test_launch.py 
[INFO] [launch]: All log files can be found below /<redacted>
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [sleep-1]: process details: cmd=[sleep, 5], cwd='None', custom_env?=False
[INFO] [sleep-1]: process started with pid [16424]
^C[WARNING] [launch]: user interrupted with ctrl-c (SIGINT)
[ERROR] [sleep-1]: process has died [pid 16424, exit code -2, cmd 'sleep 5'].
[INFO] [launch.user]: This message prints properly.
edit retag flag offensive close merge delete

2 Answers

Sort by » oldest newest most voted
1

answered 2021-04-21 09:15:31 -0500

Chuck Claunch gravatar image

Interesting finding here, this works if I use OpaqueFunction as my on_exit action. This will for for my needs, but I still find it odd that these other actions work but ExecuteProcess does not.

from launch import LaunchDescription
from launch.actions import ExecuteProcess, LogInfo, OpaqueFunction


def exit_process_function(_launch_context):
    """Print something."""
    print('exit_process_function() called')


def generate_launch_description():
    """Launch the thing."""

    return LaunchDescription([
        ExecuteProcess(
            cmd=['sleep', '5'],
            log_cmd=True,
            sigterm_timeout='0',
            sigkill_timeout='0',
            on_exit=[
                OpaqueFunction(
                    function=exit_process_function
                ),
                LogInfo(msg='This message prints properly.')
            ]
        )
    ])

Output:

✔  14:13 ~ # ros2 launch test_package test_launch.py 
[INFO] [launch]: All log files can be found below <redacted>
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [sleep-1]: process details: cmd=[sleep, 5], cwd='None', custom_env?=False
[INFO] [sleep-1]: process started with pid [21809]
[INFO] [sleep-1]: process has finished cleanly [pid 21809]
exit_process_function() called
[INFO] [launch.user]: This message prints properly.
✔  14:13 ~ # ros2 launch test_package test_launch.py 
[INFO] [launch]: All log files can be found below <redacted>
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [sleep-1]: process details: cmd=[sleep, 5], cwd='None', custom_env?=False
[INFO] [sleep-1]: process started with pid [21847]
^C[WARNING] [launch]: user interrupted with ctrl-c (SIGINT)
[ERROR] [sleep-1]: process has died [pid 21847, exit code -2, cmd 'sleep 5'].
exit_process_function() called
[INFO] [launch.user]: This message prints properly.
edit flag offensive delete link more
0

answered 2021-04-21 02:06:23 -0500

Joe28965 gravatar image

If you interrupt using CTRL C you don't just exit the one node you're running. You're terminating the whole program. As a result, it does not start another process (the echo).

The reason why it's still executing the LogInfo is probably because it falls under 'clean exit' of the program.

edit flag offensive delete link more

Comments

Something doesn't make sense though with that logic. If the whole program is terminated at the CTRL-C, then how could it still be running to print the LogInfo message?

Chuck Claunch gravatar image Chuck Claunch  ( 2021-04-21 07:57:42 -0500 )edit

it doesn't just simply throw the program in the bin, it's a slightly more complex shutdown than that, which is why it does create a log from the shutdown. It doesn't start something up again

Joe28965 gravatar image Joe28965  ( 2021-04-21 10:41:34 -0500 )edit

Question Tools

2 followers

Stats

Asked: 2021-04-20 16:04:01 -0500

Seen: 1,886 times

Last updated: Apr 21 '21