-
Notifications
You must be signed in to change notification settings - Fork 43
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
Revamp of rmw_context_impl_s #307
Conversation
That way we can completely hide the implementation in rmw_context_impl_s.cpp. Signed-off-by: Chris Lalancette <[email protected]>
We can just do this work right in the constructor, which simplifies it. Signed-off-by: Chris Lalancette <[email protected]>
Signed-off-by: Chris Lalancette <[email protected]>
Signed-off-by: Chris Lalancette <[email protected]>
We only need it during construction, so only use it there. Signed-off-by: Chris Lalancette <[email protected]>
Signed-off-by: Chris Lalancette <[email protected]>
What we do here is to create a global map between a Data pointer, and its shared_ptr equivalent. When we create a new Data ptr via rmw_context_impl_s, we add it to the map. When we delete a Data ptr via rmw_context_impl_s, we remove it from the map. When we get a graph callback, we look to see if the pointer is in the map; if so, we get the shared_ptr. Because of this, we are guaranteed that the Data pointer will not be removed while we are using it. Signed-off-by: Chris Lalancette <[email protected]>
In particular, since all of the data is owned by Data, move all of the functionality into there as well. Then it is clear who owns all of it, instead of it being split across rmw_context_impl_s and Data. Signed-off-by: Chris Lalancette <[email protected]>
I added in this comment a summary of test failures. |
Signed-off-by: Chris Lalancette <[email protected]>
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.
Thanks for cleaning this up! Left some feedback to consider!
// Bundle all class members into a data struct which can be passed as a | ||
// weak ptr to various threads for thread-safe access without capturing | ||
// "this" ptr by reference. | ||
class Data final |
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.
Nit: For better readability, can we first define Data
and all its members here first before we implement them later in this file?
///=============================================================================
class rmw_context_impl_s::Data
{
public:
Data(...);
rmw_ret_t shutdown();
...
private:
z_owned_session_t session_;
...
};
///=============================================================================
rmw_context_impl_s::Data::Data(...)
{
...
}
That should also minimize the diff.
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.
Yeah, we can do that. I generally find that unnecessarily verbose, because you are doing the same thing but with more lines.
That said, I don't feel super strongly about it. Let me know if you really prefer that style and I can switch to it.
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.
Not a strong requirement from my end
Signed-off-by: Chris Lalancette <[email protected]>
Signed-off-by: Chris Lalancette <[email protected]>
This PR is an attempt to fix two particular issues surrounding rmw_context_impl_s:
graph_sub_data_handler
call could attempt to access aData
pointer that had already been freed.graph_sub_data_handler
was being called by Zenoh whileData::shutdown
was trying to destroy the session. This would end up in an AB/BA deadlock.It's probably best to review this PR patch-by-patch, as this will show you how I got to this solution, but in short:
Data::subscribe_to_ros_graph
method and just put the code inline.Data::is_initialized_
member.Data::allocator_
member.Data::liveliness_str_
; we only need it during the constructor.final
, and removeenable_shared_from_this
(we don't currently need it).graph_sub_data_handler
, but it is strictly used as a key to look up the shared_ptr. Once we have the shared_ptr, we are guaranteed that the structure will not be deleted while we are using it.rmw_context_impl_s
is a thin wrapper over Data, that really only passes through calls and manages the addition and removal of Data from the global map.With all of this in place, I can no longer reproduce the crash that I was seeing locally. Also, with this and with ros2/rclpy#1353 in place, I am down to a single reproducible failing test across [
rcl
,rcl_action
,rcl_lifecycle
,rclcpp
,rclcpp_action
,rclcpp_lifecycle
,rclpy
,test_rclcpp
,test_communication
].