diff --git a/src/shrpx_http2_session.cc b/src/shrpx_http2_session.cc index 231f81db..6d5f4d43 100644 --- a/src/shrpx_http2_session.cc +++ b/src/shrpx_http2_session.cc @@ -171,6 +171,13 @@ void initiate_connection_cb(struct ev_loop *loop, ev_timer *w, int revents) { } } // namespace +namespace { +void prepare_cb(struct ev_loop *loop, ev_prepare *w, int revents) { + auto http2session = static_cast(w->data); + http2session->check_retire(); +} +} // namespace + Http2Session::Http2Session(struct ev_loop *loop, SSL_CTX *ssl_ctx, Worker *worker, const std::shared_ptr &group, @@ -211,6 +218,10 @@ Http2Session::Http2Session(struct ev_loop *loop, SSL_CTX *ssl_ctx, ev_timer_init(&initiate_connection_timer_, initiate_connection_cb, 0., 0.); initiate_connection_timer_.data = this; + + ev_prepare_init(&prep_, prepare_cb); + prep_.data = this; + ev_prepare_start(loop, &prep_); } Http2Session::~Http2Session() { @@ -230,6 +241,8 @@ int Http2Session::disconnect(bool hard) { conn_.rlimit.stopw(); conn_.wlimit.stopw(); + ev_prepare_stop(conn_.loop, &prep_); + ev_timer_stop(conn_.loop, &initiate_connection_timer_); ev_timer_stop(conn_.loop, &settings_timer_); ev_timer_stop(conn_.loop, &connchk_timer_); @@ -2195,4 +2208,18 @@ void Http2Session::on_timeout() { } } +void Http2Session::check_retire() { + if (!group_->retired) { + return; + } + + ev_prepare_stop(conn_.loop, &prep_); + + auto last_stream_id = nghttp2_session_get_last_proc_stream_id(session_); + nghttp2_submit_goaway(session_, NGHTTP2_FLAG_NONE, last_stream_id, + NGHTTP2_NO_ERROR, nullptr, 0); + + signal_write(); +} + } // namespace shrpx diff --git a/src/shrpx_http2_session.h b/src/shrpx_http2_session.h index 318d87cb..a3b0a223 100644 --- a/src/shrpx_http2_session.h +++ b/src/shrpx_http2_session.h @@ -200,6 +200,11 @@ public: void on_timeout(); + // This is called periodically using ev_prepare watcher, and if + // group_ is retired (backend has been replaced), send GOAWAY to + // shutdown the connection. + void check_retire(); + enum { // Disconnected DISCONNECTED, @@ -241,6 +246,7 @@ private: ev_timer connchk_timer_; // timer to initiate connection. usually, this fires immediately. ev_timer initiate_connection_timer_; + ev_prepare prep_; DList dconns_; DList streams_; std::function read_, write_;