@@ -207,16 +207,16 @@ class Chttp2ServerListener : public Server::ListenerInterface {
207
207
grpc_pollset_set* const interested_parties_;
208
208
};
209
209
210
- ActiveConnection (grpc_pollset* accepting_pollset, AcceptorPtr acceptor,
210
+ ActiveConnection (RefCountedPtr<Chttp2ServerListener> listener,
211
+ grpc_pollset* accepting_pollset, AcceptorPtr acceptor,
211
212
EventEngine* event_engine, const ChannelArgs& args,
212
213
MemoryOwner memory_owner);
213
214
214
215
void Orphan () override ;
215
216
216
217
void SendGoAway ();
217
218
218
- void Start (RefCountedPtr<Chttp2ServerListener> listener,
219
- OrphanablePtr<grpc_endpoint> endpoint, const ChannelArgs& args);
219
+ void Start (OrphanablePtr<grpc_endpoint> endpoint, const ChannelArgs& args);
220
220
221
221
// Needed to be able to grab an external ref in
222
222
// Chttp2ServerListener::OnAccept()
@@ -228,6 +228,9 @@ class Chttp2ServerListener : public Server::ListenerInterface {
228
228
229
229
RefCountedPtr<Chttp2ServerListener> listener_;
230
230
Mutex mu_ ABSL_ACQUIRED_AFTER (&listener_->mu_);
231
+ // Was ActiveConnection::Start() invoked? Used to determine whether
232
+ // tcp_server needs to be unreffed.
233
+ bool connection_started_ ABSL_GUARDED_BY (&mu_) = false;
231
234
// Set by HandshakingState before the handshaking begins and reset when
232
235
// handshaking is done.
233
236
OrphanablePtr<HandshakingState> handshaking_state_ ABSL_GUARDED_BY (&mu_);
@@ -390,11 +393,16 @@ Chttp2ServerListener::ActiveConnection::HandshakingState::HandshakingState(
390
393
}
391
394
392
395
Chttp2ServerListener::ActiveConnection::HandshakingState::~HandshakingState () {
396
+ bool connection_started = false ;
397
+ {
398
+ MutexLock lock (&connection_->mu_ );
399
+ connection_started = connection_->connection_started_ ;
400
+ }
393
401
if (accepting_pollset_ != nullptr ) {
394
402
grpc_pollset_set_del_pollset (interested_parties_, accepting_pollset_);
395
403
}
396
404
grpc_pollset_set_destroy (interested_parties_);
397
- if (connection_->listener_ != nullptr &&
405
+ if (connection_started && connection_->listener_ != nullptr &&
398
406
connection_->listener_ ->tcp_server_ != nullptr ) {
399
407
grpc_tcp_server_unref (connection_->listener_ ->tcp_server_ );
400
408
}
@@ -566,10 +574,12 @@ void Chttp2ServerListener::ActiveConnection::HandshakingState::OnHandshakeDone(
566
574
//
567
575
568
576
Chttp2ServerListener::ActiveConnection::ActiveConnection (
577
+ RefCountedPtr<Chttp2ServerListener> listener,
569
578
grpc_pollset* accepting_pollset, AcceptorPtr acceptor,
570
579
EventEngine* event_engine, const ChannelArgs& args,
571
580
MemoryOwner memory_owner)
572
- : handshaking_state_(memory_owner.MakeOrphanable<HandshakingState>(
581
+ : listener_(std::move(listener)),
582
+ handshaking_state_ (memory_owner.MakeOrphanable<HandshakingState>(
573
583
Ref (), accepting_pollset, std::move(acceptor), args)),
574
584
event_engine_(event_engine) {
575
585
GRPC_CLOSURE_INIT (&on_close_, ActiveConnection::OnClose, this ,
@@ -626,12 +636,11 @@ void Chttp2ServerListener::ActiveConnection::SendGoAway() {
626
636
}
627
637
628
638
void Chttp2ServerListener::ActiveConnection::Start (
629
- RefCountedPtr<Chttp2ServerListener> listener,
630
639
OrphanablePtr<grpc_endpoint> endpoint, const ChannelArgs& args) {
631
- listener_ = std::move (listener);
632
640
RefCountedPtr<HandshakingState> handshaking_state_ref;
633
641
{
634
642
MutexLock lock (&mu_);
643
+ connection_started_ = true ;
635
644
// If the Connection is already shutdown at this point, it implies the
636
645
// owning Chttp2ServerListener and all associated ActiveConnections have
637
646
// been orphaned.
@@ -863,34 +872,32 @@ void Chttp2ServerListener::OnAccept(void* arg, grpc_endpoint* tcp,
863
872
auto memory_owner = self->memory_quota_ ->CreateMemoryOwner ();
864
873
EventEngine* const event_engine = self->args_ .GetObject <EventEngine>();
865
874
auto connection = memory_owner.MakeOrphanable <ActiveConnection>(
866
- accepting_pollset, std::move (acceptor ), event_engine, args ,
867
- std::move (memory_owner));
875
+ self-> RefAsSubclass <Chttp2ServerListener>( ), accepting_pollset ,
876
+ std::move (acceptor), event_engine, args, std::move ( memory_owner));
868
877
// Hold a ref to connection to allow starting handshake outside the
869
878
// critical region
870
879
RefCountedPtr<ActiveConnection> connection_ref = connection->Ref ();
871
- RefCountedPtr<Chttp2ServerListener> listener_ref;
872
880
{
873
881
MutexLock lock (&self->mu_ );
874
882
// Shutdown the the connection if listener's stopped serving or if the
875
883
// connection manager has changed.
876
884
if (!self->shutdown_ && self->is_serving_ &&
877
885
connection_manager == self->connection_manager_ ) {
878
- // The ref for both the listener and tcp_server need to be taken in the
879
- // critical region after having made sure that the listener has not been
880
- // Orphaned, so as to avoid heap-use-after-free issues where `Ref()` is
881
- // invoked when the listener is already shutdown. Note that the listener
882
- // holds a ref to the tcp_server but this ref is given away when the
883
- // listener is orphaned (shutdown). A connection needs the tcp_server to
884
- // outlast the handshake since the acceptor needs it.
886
+ // The ref for the tcp_server needs to be taken in the critical region
887
+ // after having made sure that the listener has not been Orphaned, so as
888
+ // to avoid heap-use-after-free issues where `Ref()` is invoked when the
889
+ // listener is already shutdown. Note that the listener holds a ref to the
890
+ // tcp_server but this ref is given away when the listener is orphaned
891
+ // (shutdown). A connection needs the tcp_server to outlast the handshake
892
+ // since the acceptor needs it.
885
893
if (self->tcp_server_ != nullptr ) {
886
894
grpc_tcp_server_ref (self->tcp_server_ );
887
895
}
888
- listener_ref = self->RefAsSubclass <Chttp2ServerListener>();
889
896
self->connections_ .emplace (connection.get (), std::move (connection));
890
897
}
891
898
}
892
- if (connection == nullptr && listener_ref != nullptr ) {
893
- connection_ref->Start (std::move (listener_ref), std::move ( endpoint), args);
899
+ if (connection == nullptr ) {
900
+ connection_ref->Start (std::move (endpoint), args);
894
901
}
895
902
}
896
903
0 commit comments