nghttpx: Keep reading after backend write failed

Because of bidirectional nature of TCP, we may fail write(2), but have
still pending read in TCP buffer, which may contain response body.  To
forward them, we should keep reading until get EOF from backend.

To avoid stalling HTTP/1 upload when request buffer is full, and we
have received complete response from backend, drop connection in that
case.
This commit is contained in:
Tatsuhiro Tsujikawa 2016-12-24 22:50:02 +09:00
parent 841ac75c3e
commit a0ce5ea9ab
3 changed files with 27 additions and 5 deletions

View File

@ -2022,7 +2022,12 @@ int Http2Session::write_clear() {
} }
if (nwrite < 0) { if (nwrite < 0) {
return nwrite; // We may have pending data in receive buffer which may
// contain part of response body. So keep reading. Invoke
// read event to get read(2) error just in case.
ev_feed_event(conn_.loop, &conn_.rev, EV_READ);
wb_.drain(wb_.rleft());
break;
} }
wb_.drain(nwrite); wb_.drain(nwrite);
@ -2132,7 +2137,12 @@ int Http2Session::write_tls() {
} }
if (nwrite < 0) { if (nwrite < 0) {
return nwrite; // We may have pending data in receive buffer which may
// contain part of response body. So keep reading. Invoke
// read event to get read(2) error just in case.
ev_feed_event(conn_.loop, &conn_.rev, EV_READ);
wb_.drain(wb_.rleft());
break;
} }
wb_.drain(nwrite); wb_.drain(nwrite);

View File

@ -1116,7 +1116,12 @@ int HttpDownstreamConnection::write_clear() {
} }
if (nwrite < 0) { if (nwrite < 0) {
return nwrite; // We may have pending data in receive buffer which may contain
// part of response body. So keep reading. Invoke read event
// to get read(2) error just in case.
ev_feed_event(conn_.loop, &conn_.rev, EV_READ);
input->drain(input->rleft());
break;
} }
input->drain(nwrite); input->drain(nwrite);
@ -1236,7 +1241,12 @@ int HttpDownstreamConnection::write_tls() {
} }
if (nwrite < 0) { if (nwrite < 0) {
return nwrite; // We may have pending data in receive buffer which may contain
// part of response body. So keep reading. Invoke read event
// to get read(2) error just in case.
ev_feed_event(conn_.loop, &conn_.rev, EV_READ);
input->drain(input->rleft());
break;
} }
input->drain(nwrite); input->drain(nwrite);

View File

@ -1184,7 +1184,9 @@ int HttpsUpstream::on_downstream_body_complete(Downstream *downstream) {
resp.connection_close = true; resp.connection_close = true;
} }
if (req.connection_close || resp.connection_close) { if (req.connection_close || resp.connection_close ||
// To avoid to stall upload body
downstream->get_request_state() != Downstream::MSG_COMPLETE) {
auto handler = get_client_handler(); auto handler = get_client_handler();
handler->set_should_close_after_write(true); handler->set_should_close_after_write(true);
} }