executive_smach icon indicating copy to clipboard operation
executive_smach copied to clipboard

Smach/Python does not respond to Ctrl+C when inside a Concurrency Container

Open jhoare opened this issue 11 years ago • 16 comments

I am using SMACH in that the top-level container is a Concurrency Container. If I want to Ctrl+C the process, it never responds. I believe this is due to the fact that the Concurrency Container is all running in child threads and not in the Main thread.

jhoare avatar Mar 11 '13 21:03 jhoare

Are you running the concurrency bare, or are you putting it inside of an IntrospectionServer? If it's the former, you should be able to get your ctrl-c-ability by changing this:

outcome = my_smach_con.execute()

Into this:

# Create a thread to execute the smach container
smach_thread = threading.Thread(target=my_smach_con.execute)
smach_thread.start()

# Wait for ctrl-c
rospy.spin()

# Request the container to preempt
my_smach_con.request_preempt()

# Block until everything is preempted 
# (you could do something more complicated to get the execution outcome if you want it)
smach_thread.join()

jbohren avatar Mar 12 '13 07:03 jbohren

We do have it attached to an Introspection Server.

We are using a Concurrence behavior at the top most level to also run a Monitor State which monitors for an incoming ROS message which shuts down the entire SMACH state machine.

Edit: The monitor state runs concurrently with the entire state machine, if I wasn't explicit before. Also, I'm using the version released with Fuerte, I'm not sure if that is the latest version or not.

jhoare avatar Mar 12 '13 19:03 jhoare

Ok, I'll see if I can repro.

jbohren avatar Mar 12 '13 19:03 jbohren

Do you call stop() on the IntrospectionServer after rospy.spin()?

jbohren avatar Mar 12 '13 20:03 jbohren

I have no calls to rospy.spin() in the code. The concurrence container's execute() function is called and this is where it is blocking (and the ctrl+c is not caught)

I do stop the introspection server, however, after the execute() call returns.

jhoare avatar Mar 12 '13 21:03 jhoare

Sorry, what I meant before was an ActionServerWrapper instead of an IntrospectionServer. If you call the bare execute() member function directly, it will block, and there's nothing to tell it to preempt when the interrupt signal comes in. You should try the code that I posted above, when you run the concurrence in a separate thread, and then use the standard ROS signal interrupt handler to stop the call to rospy.spin() and then you can request that your concurrence preempts itself.

jbohren avatar Mar 12 '13 21:03 jbohren

Any progress?

jbohren avatar Mar 14 '13 14:03 jbohren

Sorry, I haven't really had a chance to look at this. However, the way we're using SMACH wouldn't allow us to do exactly that, as a process may start up and tear down a state machine many times in its lifetime.

jhoare avatar Mar 14 '13 15:03 jhoare

Well even if it's not that code exactly, can you add a rospy shutdown hook which calls request_preempt() on your top-level container?

jbohren avatar Mar 14 '13 15:03 jbohren

Thanks for those hints Jonathan! I also had troubles with ctrl+c and smach. Unfortunately preempting the state machine after rospy.spin() returned due to crtl+c (shown in your first comment) doesn't shutdown concurrent state containers properly as they do not wait for their threads to terminate then (because smach.is_shutdown() is false). Using the rospy shutdown hook didn't work with a concurrent container.

Therefore I should trigger my preemption monitor state in real world execution for proper shutdown.

orzechow avatar Dec 13 '13 19:12 orzechow

Has this been fixed yet? I'm seeing the same thing in Hydro

athackst avatar Mar 14 '15 18:03 athackst

@athackst What does your top-level script look like? I was never able to reproduce this.

jbohren avatar Mar 15 '15 17:03 jbohren

I did you one better and made a package for you so you can test here. I think the problem might be the thread.wait() command. I changed it to poll instead on my branch feature/ConcurrencyFIx and it seems to fix the problem. Can you reproduce it using the package I provided?

athackst avatar Mar 17 '15 21:03 athackst

@athackst Thanks! That made it really easy to resolve. See the fix here: https://github.com/athackst/smach_concurrency_tests/pull/1

jbohren avatar Mar 18 '15 00:03 jbohren

Why should I have to implement a thread pool? Shouldn't the concurrency should do the threading for me? This fix makes that unnecessary : https://github.com/ros/executive_smach/pull/35

athackst avatar Mar 18 '15 01:03 athackst

Why should I have to implement a thread pool? Shouldn't the concurrency should do the threading for me? This fix makes that unnecessary : #35

We can discuss that over in #35

jbohren avatar Mar 18 '15 01:03 jbohren