Skip to content
This repository has been archived by the owner on Mar 28, 2022. It is now read-only.

Commit

Permalink
Ensured server call delete happens after all OnDone handlers are called.
Browse files Browse the repository at this point in the history
  • Loading branch information
benh committed Jul 13, 2020
1 parent 442668e commit 70f69ed
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 4 deletions.
8 changes: 8 additions & 0 deletions stout/grpc/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ namespace grpc {
ServerCallBase::ServerCallBase(std::unique_ptr<ServerContext>&& context, CallType type)
: status_(ServerCallStatus::Ok), context_(std::move(context)), type_(type)
{
// NOTE: we rely on the explicit design of Notification where the
// ***first*** handler added via 'Watch()' will be the last handler
// that gets executed in order to trigger 'donedonedone_' after
// we've triggered all of the other 'OnDone()' handlers.
done_.Watch([this](bool cancelled) {
donedonedone_.Notify(cancelled);
});

// NOTE: 'context_->OnDone()' NOT 'this->OnDone()'.
context_->OnDone([this](bool cancelled) {
// NOTE: emperical evidence shows that gRPC may invoke the done
Expand Down
16 changes: 12 additions & 4 deletions stout/grpc/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,14 @@ class ServerCallBase : public CallBase
}

private:
friend class Server;

template <typename F>
void OnDoneDoneDone(F&& f)
{
donedonedone_.Watch(f);
}

ServerCallStatus write(
::grpc::ByteBuffer* buffer,
::grpc::WriteOptions options)
Expand Down Expand Up @@ -814,6 +822,7 @@ class ServerCallBase : public CallBase
std::unique_ptr<ServerContext> context_;

Notification<bool> done_;
Notification<bool> donedonedone_;

CallType type_;
};
Expand Down Expand Up @@ -1064,10 +1073,9 @@ std::enable_if_t<
auto call = borrow(
new ServerCall<Request, Response>(std::move(context)),
[](auto* call) {
// NOTE: see note in ServerCallBase constructor as to the
// invariant that we must set up our 'OnDone' handler
// *after* the ServerCallBase constructor.
call->OnDone([](auto* call, bool) {
// NOTE: using private 'OnDoneDoneDone()' which gets invoked
// *after* all of the other 'OnDone()' handlers.
call->OnDoneDoneDone([call](bool) {
delete call;
});
});
Expand Down

0 comments on commit 70f69ed

Please sign in to comment.