I prototyped a bit to investigate this behaviour. Ran the following node:
#!/usr/bin/env python
import rospy
from threading import Lock
from std_msgs.msg import String
mutex = Lock()
def handler(data):
print "Handle called"
mutex.acquire()
print "Handle executed"
import time; time.sleep(10)
mutex.release()
rospy.init_node('test')
rospy.Subscriber('/foo', String, handler)
rospy.spin()
When I publish several individual messages I see that indeed the handler is getting called on another thread while the current handler is still in execution.
rospy pub /foo std_msgs/String "data: 'hello'"
ctrl-c
rospy pub /foo std_msgs/String "data: 'hello'"
ctrl-c
rospy pub /foo std_msgs/String "data: 'hello'"
ctrl-c
I see the output:
Handle called
Handle executed
Handle called
Handle called
... several seconds later
Handle executed
... several seconds later
Handle executed
However, when I publish a msg periodically from the same publish call:
rospy pub /foo std_msgs/String "data: 'hello'"-r 1 # publish once a second
I see this:
Handle called
Handle executed
... 10 seconds pass
Handle called
Handle executed
... 10 seconds pass
Handle called
Handle executed
I know the message is being published once a second, yet it doesn't spawn a new thread for the callback - so something is throttling the msgs until they have been handled.
So the behavior seems to diff depending on if the msgs are arriving from the same process or multiple processes.
I confirmed that it wasn't just a behaviour of rostopic pub by writing a simple node that publishes a msg every second and it behaves the same.
I haven't looked at the ROS code yet so not sure if its the ROS publisher or subscriber code that is throttling in the same process case.
So if you are publishing a topic from a single source then strictly speaking it seems like you don't need a mutex to protect about re-entry by the same topic handler.
However, in my opinion, considering that you (or a future developer) might call the same work function from a different callback or from a timer or from a main loop, or since you can use the same handler for multiple topics (that might come from different processes) and since adding a mutex is pretty easy and low effort and overhead it seems reasonable.