nghttpx: Fix possible deadlock due to exhaustion of send window
This commit is contained in:
parent
c81e87bf37
commit
69b9ce6b68
|
@ -204,6 +204,20 @@ 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) {
|
||||||
|
// This is important because it will handle flow control
|
||||||
|
// stuff.
|
||||||
|
if(downstream->get_upstream()->resume_read(SHRPX_NO_BUFFER,
|
||||||
|
downstream) != 0) {
|
||||||
|
// In this case, downstream may be deleted.
|
||||||
|
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check dconn is still alive because Upstream::resume_read()
|
||||||
|
// may delete downstream which will delete dconn.
|
||||||
|
if(sd->dconn == nullptr) {
|
||||||
|
return NGHTTP2_ERR_DEFERRED;
|
||||||
|
}
|
||||||
|
|
||||||
if(downstream->get_request_state() == Downstream::MSG_COMPLETE) {
|
if(downstream->get_request_state() == Downstream::MSG_COMPLETE) {
|
||||||
if(!downstream->get_upgrade_request() ||
|
if(!downstream->get_upgrade_request() ||
|
||||||
(downstream->get_response_state() == Downstream::HEADER_COMPLETE &&
|
(downstream->get_response_state() == Downstream::HEADER_COMPLETE &&
|
||||||
|
@ -216,18 +230,6 @@ ssize_t http2_data_read_callback(nghttp2_session *session,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// This is important because it will handle flow control
|
|
||||||
// stuff.
|
|
||||||
if(downstream->get_upstream()->resume_read(SHRPX_NO_BUFFER,
|
|
||||||
downstream) != 0) {
|
|
||||||
// In this case, downstream may be deleted.
|
|
||||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
|
||||||
}
|
|
||||||
// Check dconn is still alive because Upstream::resume_read()
|
|
||||||
// may delete downstream which will delete dconn.
|
|
||||||
if(sd->dconn == nullptr) {
|
|
||||||
return NGHTTP2_ERR_DEFERRED;
|
|
||||||
}
|
|
||||||
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,
|
||||||
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,
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue