Commit 69b9ce6b authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

nghttpx: Fix possible deadlock due to exhaustion of send window

parent c81e87bf
...@@ -204,18 +204,6 @@ ssize_t http2_data_read_callback(nghttp2_session *session, ...@@ -204,18 +204,6 @@ ssize_t http2_data_read_callback(nghttp2_session *session,
return NGHTTP2_ERR_CALLBACK_FAILURE; return NGHTTP2_ERR_CALLBACK_FAILURE;
} }
if(nread == 0) { if(nread == 0) {
if(downstream->get_request_state() == Downstream::MSG_COMPLETE) {
if(!downstream->get_upgrade_request() ||
(downstream->get_response_state() == Downstream::HEADER_COMPLETE &&
!downstream->get_upgraded())) {
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
} else {
downstream->disable_downstream_wtimer();
return NGHTTP2_ERR_DEFERRED;
}
break;
} else {
// This is important because it will handle flow control // This is important because it will handle flow control
// stuff. // stuff.
if(downstream->get_upstream()->resume_read(SHRPX_NO_BUFFER, if(downstream->get_upstream()->resume_read(SHRPX_NO_BUFFER,
...@@ -223,11 +211,25 @@ ssize_t http2_data_read_callback(nghttp2_session *session, ...@@ -223,11 +211,25 @@ ssize_t http2_data_read_callback(nghttp2_session *session,
// In this case, downstream may be deleted. // In this case, downstream may be deleted.
return NGHTTP2_ERR_CALLBACK_FAILURE; return NGHTTP2_ERR_CALLBACK_FAILURE;
} }
// Check dconn is still alive because Upstream::resume_read() // Check dconn is still alive because Upstream::resume_read()
// may delete downstream which will delete dconn. // may delete downstream which will delete dconn.
if(sd->dconn == nullptr) { if(sd->dconn == nullptr) {
return NGHTTP2_ERR_DEFERRED; return NGHTTP2_ERR_DEFERRED;
} }
if(downstream->get_request_state() == Downstream::MSG_COMPLETE) {
if(!downstream->get_upgrade_request() ||
(downstream->get_response_state() == Downstream::HEADER_COMPLETE &&
!downstream->get_upgraded())) {
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
} else {
downstream->disable_downstream_wtimer();
return NGHTTP2_ERR_DEFERRED;
}
break;
} else {
if(evbuffer_get_length(body) == 0) { if(evbuffer_get_length(body) == 0) {
// Check get_request_state() == MSG_COMPLETE just in case // Check get_request_state() == MSG_COMPLETE just in case
if(downstream->get_request_state() == Downstream::MSG_COMPLETE) { if(downstream->get_request_state() == Downstream::MSG_COMPLETE) {
......
...@@ -1101,13 +1101,15 @@ ssize_t downstream_data_read_callback(nghttp2_session *session, ...@@ -1101,13 +1101,15 @@ ssize_t downstream_data_read_callback(nghttp2_session *session,
downstream->disable_upstream_wtimer(); downstream->disable_upstream_wtimer();
} }
if(nread == 0 && ((*data_flags) & NGHTTP2_DATA_FLAG_EOF) == 0) { if(nread == 0) {
if(downstream->resume_read(SHRPX_NO_BUFFER) != 0) { if(downstream->resume_read(SHRPX_NO_BUFFER) != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE; return NGHTTP2_ERR_CALLBACK_FAILURE;
} }
if(((*data_flags) & NGHTTP2_DATA_FLAG_EOF) == 0) {
return NGHTTP2_ERR_DEFERRED; return NGHTTP2_ERR_DEFERRED;
} }
}
return nread; return nread;
} }
} // namespace } // namespace
......
...@@ -834,13 +834,15 @@ ssize_t spdy_data_read_callback(spdylay_session *session, ...@@ -834,13 +834,15 @@ ssize_t spdy_data_read_callback(spdylay_session *session,
downstream->disable_upstream_wtimer(); downstream->disable_upstream_wtimer();
} }
if(nread == 0 && *eof != 1) { if(nread == 0) {
if(downstream->resume_read(SHRPX_NO_BUFFER) != 0) { if(downstream->resume_read(SHRPX_NO_BUFFER) != 0) {
return SPDYLAY_ERR_CALLBACK_FAILURE; return SPDYLAY_ERR_CALLBACK_FAILURE;
} }
if(*eof != 1) {
return SPDYLAY_ERR_DEFERRED; return SPDYLAY_ERR_DEFERRED;
} }
}
return nread; return nread;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment