Commit a0ce5ea9 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

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.
parent 841ac75c
......@@ -2022,7 +2022,12 @@ int Http2Session::write_clear() {
}
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);
......@@ -2132,7 +2137,12 @@ int Http2Session::write_tls() {
}
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);
......
......@@ -1116,7 +1116,12 @@ int HttpDownstreamConnection::write_clear() {
}
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);
......@@ -1236,7 +1241,12 @@ int HttpDownstreamConnection::write_tls() {
}
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);
......
......@@ -1184,7 +1184,9 @@ int HttpsUpstream::on_downstream_body_complete(Downstream *downstream) {
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();
handler->set_should_close_after_write(true);
}
......
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