[c++ grpc] Drop client callback after executing
After executing the client callback upon receiving a response, clear the stored callback to prevent a shared_ptr cycle. Previously, when the callback function was not cleared, if the callback happened to store the unary_call_result that it was invoked with (like wait_callback does), there would be a shared_ptr cycle: the callback would have a shared_ptr to the unary_call_result, which was keeping its parent client_unary_call_data alive. This client_unary_call_data had a copy of the callback function, which had a shared_ptr to the unary_call_result. This change resets the callback to empty after is has been executed, breaking the cycle.
This commit is contained in:
Родитель
f96af1ffe1
Коммит
554125145d
|
@ -40,7 +40,8 @@ different versioning scheme, following the Haskell community's
|
|||
causing a stack overflow.
|
||||
* Guard against min/max being function-style macros in more places.
|
||||
* Provide compile-time access to metadata about gRPC services and methods.
|
||||
|
||||
* Using `bond::ext::gRPC::wait_callback` no longer causes a shared_ptr cycle
|
||||
and the resulting resource leak.
|
||||
|
||||
### C# ###
|
||||
|
||||
|
|
|
@ -51,14 +51,14 @@ struct client_unary_call_data
|
|||
std::shared_ptr<TThreadPool> _threadPool;
|
||||
/// A response reader.
|
||||
std::unique_ptr<grpc::ClientAsyncResponseReader<bond::bonded<TResponse>>> _responseReader;
|
||||
/// The arguments to pass back into the client callback. Also doubles as
|
||||
/// The arguments to pass back into the client callback. Also doubles as
|
||||
/// storage for the response, status, and context.
|
||||
unary_call_result<TResponse> _callbackArgs;
|
||||
/// A pointer to ourselves used to keep us alive while waiting to receive
|
||||
/// the response.
|
||||
std::shared_ptr<client_unary_call_data> _self;
|
||||
/// The user code to invoke when a response is received.
|
||||
CallbackType _cb;
|
||||
/// A pointer to ourselves used to keep us alive while waiting to
|
||||
/// receive the response.
|
||||
std::shared_ptr<client_unary_call_data> _self;
|
||||
|
||||
client_unary_call_data(
|
||||
std::shared_ptr<grpc::ChannelInterface> channel,
|
||||
|
@ -71,8 +71,8 @@ struct client_unary_call_data
|
|||
_threadPool(std::move(threadPool)),
|
||||
_responseReader(),
|
||||
_callbackArgs(context),
|
||||
_self(),
|
||||
_cb(cb)
|
||||
_cb(cb),
|
||||
_self()
|
||||
{
|
||||
BOOST_ASSERT(_channel);
|
||||
BOOST_ASSERT(_ioManager);
|
||||
|
@ -133,6 +133,11 @@ struct client_unary_call_data
|
|||
_ioManager.reset();
|
||||
_threadPool.reset();
|
||||
_responseReader.reset();
|
||||
_cb = {};
|
||||
|
||||
// In case we're the only reference keeping ourselves alive, we need
|
||||
// to clear _self last so we don't attempt to access a local after
|
||||
// this instance has been destroyed.
|
||||
_self.reset();
|
||||
}
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче