Conversation
|
Seeing this do we have race conditions related to calling spin* from multiple threads? It lookslike I could call spin_some in one thread then cancel, and spin_some in another thread and if the timing is right both will continue to spin, since the cancel has been reset by the spin_some? People calling spin from multiple threads has been a problem in ROS1 |
|
The spin functions are not thread safe, so I'd say that's unsupported behavior. |
|
If users want parallelized execution they should use the |
refactor executor::cancel to use a spinning state
|
Rerunning CI with changes from @wjwwood to ensure spin* cannot be entered by multiple threads at the same time. http://ci.ros2.org/job/ros2_batch_ci_linux/591/ |
|
Lgtm, but someone else should review it as well. |
rclcpp/src/rclcpp/executor.cpp
Outdated
There was a problem hiding this comment.
Manually resetting this is not safe when exceptions happen. Since it can't be done in a finally block this should use RAII to ensure that value gets reset to false.
Same below.
There was a problem hiding this comment.
Do you suggest setting it to false in the destructor, then?
There was a problem hiding this comment.
I refer to calling spinning.exchange(true) before in this function. If an exception happens afterwards it doesn't get set back to false. This should use RAII (like a scoped mutex lock) to ensure setting the value back in any case.
There was a problem hiding this comment.
Got it.
I was trying to avoid adding mutexes to Executor where they're not needed. But mutex and lock_guard are the most suited to RAII-style management of this state. Maybe this would work with try_lock instead of lock so that we throw an exception if the Executor is already spinning instead of blocking.
@wjwwood, since you implemented about half of this PR, any thoughts?
There was a problem hiding this comment.
Yeah I'll send another pr asap.
There was a problem hiding this comment.
Yeah, my first pass at the strategy I suggested was not successful (deadlock) and it makes the code a lot more confusing.
There was a problem hiding this comment.
Sorry, I just realized you were expecting me to do this 😄. I totally misread it, but anyways I just pushed my fix. I did it by implementing what's called a scope exit or scope guard. Boost has a scope exit and so does the D language. There's some interesting discussion about including something like this in the c++ std library at some point. Anyways this should work us and might be useful else where too.
There was a problem hiding this comment.
With this implemented should we remove the redundant setting to false at the end of the scope?
There was a problem hiding this comment.
That's a fair point, I'll push another commit.
|
New CI: |
|
Lots of Executor test failures. I'll take a look. |
|
Sorry, I actually ran the tests locally and there was a failing test, I just missed it (I am not a smart man). I fixed the issue, see 1c9eb0b. |
|
lgtm |
|
CI looks good. |
Co-authored-by: Mauro Passerino <mpasserino@irobot.com>
implement state and logic for cancelling out of Executor::spin or Executor::spin_some.