-
Notifications
You must be signed in to change notification settings - Fork 42
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
Fix replies coming in after a client is destroyed. #228
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2378,7 +2378,6 @@ rmw_destroy_client(rmw_node_t * node, rmw_client_t * client) | |
return RMW_RET_INVALID_ARGUMENT); | ||
|
||
// CLEANUP =================================================================== | ||
z_drop(z_move(client_data->zn_closure_reply)); | ||
z_drop(z_move(client_data->keyexpr)); | ||
zc_liveliness_undeclare_token(z_move(client_data->token)); | ||
|
||
|
@@ -2390,9 +2389,13 @@ rmw_destroy_client(rmw_node_t * node, rmw_client_t * client) | |
client_data->response_type_support->~ResponseTypeSupport(), rmw_zenoh_cpp::ResponseTypeSupport, | ||
); | ||
allocator->deallocate(client_data->response_type_support, allocator->state); | ||
RMW_TRY_DESTRUCTOR(client_data->~rmw_client_data_t(), rmw_client_data_t, ); | ||
|
||
allocator->deallocate(client->data, allocator->state); | ||
// See the comment about the "num_in_flight" class variable in the rmw_client_data_t class for | ||
// why we need to do this. | ||
if (!client_data->shutdown_and_query_in_flight()) { | ||
RMW_TRY_DESTRUCTOR(client_data->~rmw_client_data_t(), rmw_client_data_t, ); | ||
allocator->deallocate(client->data, allocator->state); | ||
} | ||
|
||
allocator->deallocate(const_cast<char *>(client->service_name), allocator->state); | ||
allocator->deallocate(client, allocator->state); | ||
|
@@ -2425,6 +2428,10 @@ rmw_send_request( | |
"Unable to retrieve client_data from client.", | ||
RMW_RET_INVALID_ARGUMENT); | ||
|
||
if (client_data->is_shutdown()) { | ||
return RMW_RET_ERROR; | ||
} | ||
|
||
rmw_context_impl_s * context_impl = static_cast<rmw_context_impl_s *>( | ||
client_data->context->impl); | ||
|
||
|
@@ -2479,6 +2486,10 @@ rmw_send_request( | |
z_bytes_map_drop(z_move(map)); | ||
}); | ||
|
||
// See the comment about the "num_in_flight" class variable in the rmw_client_data_t class for | ||
// why we need to do this. | ||
client_data->increment_in_flight_callbacks(); | ||
|
||
opts.attachment = z_bytes_map_as_attachment(&map); | ||
|
||
opts.target = Z_QUERY_TARGET_ALL_COMPLETE; | ||
|
@@ -2492,11 +2503,13 @@ rmw_send_request( | |
// and any number. | ||
opts.consolidation = z_query_consolidation_latest(); | ||
opts.value.payload = z_bytes_t{data_length, reinterpret_cast<const uint8_t *>(request_bytes)}; | ||
client_data->zn_closure_reply = | ||
z_closure(rmw_zenoh_cpp::client_data_handler, nullptr, client_data); | ||
z_owned_closure_reply_t zn_closure_reply = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't we check that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, good point. I'll add this in as well. |
||
z_closure(rmw_zenoh_cpp::client_data_handler, rmw_zenoh_cpp::client_data_drop, client_data); | ||
z_get( | ||
z_loan(context_impl->session), z_loan( | ||
client_data->keyexpr), "", &client_data->zn_closure_reply, &opts); | ||
z_loan(context_impl->session), | ||
z_loan(client_data->keyexpr), "", | ||
z_move(zn_closure_reply), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wondering if it makes sense for the Would it be better to keep the original implementation but ensure we free the callback with According to the z_get documentation:
Will closing the Zenoh session ensure all callbacks are freed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Right, so that is a good question. And the answer is that it is up to
I'm not 100% sure, but I believe that this is a different thing. This PR is concerned with the ownership of the closure itself. To see what I am talking about, consider that in almost all other places where we call into the Zenoh API, we use either What you are talking about is the ownership of the reply. There, we are already taking ownership of the memory during the callback (via Also, it might be worthwhile to get feedback from @JEnoch and @OlivierHecart, since they were the ones that suggested this to me to begin with. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for clarifying. I think it would be good to combine those changes in this PR as well.
Ah yeah sorry I got things mixed up but my original concern still stands on whether the callback gets freed if the client is destroyed before we receive a reply. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This is a question for the Zenoh developers, but I believe not. That's the reason for doing the |
||
&opts); | ||
|
||
return RMW_RET_OK; | ||
} | ||
|
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 decrement should be done in the
drop
function of thez_owned_closure_reply_t
. There is no guarantee that thecall
function will be called only once per query, whiledrop
will be called once per query at the end.