-
Notifications
You must be signed in to change notification settings - Fork 938
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
Add execution thread mutex. #1709
Conversation
Thanks for helping in improving MoveIt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. 👍
Seems like a workaround to me. If we merge it, it should still be cleaned up soon. Looking into it right now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -1182,8 +1187,13 @@ void TrajectoryExecutionManager::stopExecution(bool auto_clear) | |||
else if (execution_thread_) // just in case we have some thread waiting to be joined from some point in the past, we | |||
// join it now | |||
{ | |||
execution_thread_->join(); | |||
execution_thread_.reset(); | |||
execution_thread_mutex_.lock(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The lock comes too late here: a few lines before, execution_thread_
is already accessed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could remove this else if with just else statement. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was an instance of double-checked locking.
It might not be necessary here, but just removing it because the read is outside the mutex is no good argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could not make any harm, with else statement and additional check, the same thing is achieved. Isn't it? Fix me if I am wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please look up the concept.
Double-checked locking is used when the time used to lock the mutex is relevant and the mutex is usually not needed (the latter clearly being the case here).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to keep the double-check locking here, one would need to add another if (execution_thread_)
to verify that the pointer is still valid after acquiring the execution_thread_mutex_
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@livanov93: I pushed a cleanup commit, to restore the double-checked locking.
@@ -1170,8 +1170,13 @@ void TrajectoryExecutionManager::stopExecution(bool auto_clear) | |||
ROS_INFO_NAMED(name_, "Stopped trajectory execution."); | |||
|
|||
// wait for the execution thread to finish | |||
execution_thread_->join(); | |||
execution_thread_.reset(); | |||
execution_thread_mutex_.lock(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use a scoped_lock
to ensure automatic unlocking of the mutex when leaving the context instead of manual locking and unlocking.
Because it's not actually well defined what the existing mutex protects and adding a new one without making sure it's not a bug in the existing logging does not make things any more consistent. |
Basically, this mutex was implemented to avoid calling |
I know and thank you for providing a fix! The problem is that MoveIt (including the |
I totally understand you and appreciate all the contributions you have done. People usually fix what they need and they move forward. This, I imagine, is a huge problem for official maintainers. |
@v4hn, I fully understand your reasoning. If you have found a better solution, please file a PR. |
@livanov93, could you please have a look (and validate) the alternative fix filed in #1712? |
I will try to make the test soon for fix comparation, generally #1712 does not do the job for me, it stops after first preemption. |
Right now I would propose to merge this fix into Tests for such issues are still very welcome, of course! |
Congrats on getting your first MoveIt pull request merged and improving open source robotics! |
Fix race condition accessing execution_thread_ by adding a new mutex.
Description
#1481
My project was in huge need of canceling trajectory execution in quite often manner, over direct message via "stop" event on "/trajectory_execution_event" topic, or via move group interface
stop()
method. I added one more mutex for protectingexecution_thread_
variable and it worked. Definitely it is not the optimal and the most elegant solution, but is quite effective. Long simulation period confirmed it has no memory leaks.Checklist