[core] add HTTP/2 check resp finished w/ empty cq (#3111)

connection_handle_write_state() call to subrequest handler might set
r->resp_body_finished, but we need to check if r->write_queue is empty
before changing state from CON_STATE_WRITE to CON_STATE_RESPONSE_END

(If r->write_queue was already empty when the subrequest handler marked
 resp_body_finished, connection_state_machine_h2() could miss changing
 the request state to CON_STATE_RESPONSE_END)

x-ref:
  "HTTP/2 requests sometimes take very long (missing last chunk)"
  https://redmine.lighttpd.net/issues/3111
  "Slow request handling in Lighttpd 1.4.60"
  https://redmine.lighttpd.net/boards/2/topics/10063
personal/stbuehler/tests-path
Glenn Strauss 2021-10-28 02:03:22 -04:00
parent ac9c9935a2
commit 90f062cb07
1 changed files with 8 additions and 4 deletions

View File

@ -1275,17 +1275,21 @@ connection_state_machine_h2 (request_st * const h2r, connection * const con)
uint32_t dlen = max_bytes > 32768 ? 32768 : (uint32_t)max_bytes;
dlen = h2_send_cqdata(r, con, &r->write_queue, dlen);
max_bytes -= (off_t)dlen;
if (dlen) { /*(do not resched (spin) if swin empty window)*/
max_bytes -= (off_t)dlen;
if (!chunkqueue_is_empty(&r->write_queue))
resched |= 1;
}
}
{
if (chunkqueue_is_empty(&r->write_queue)) {
if (r->resp_body_finished) {
if (r->resp_body_finished && r->state == CON_STATE_WRITE) {
connection_set_state(r, CON_STATE_RESPONSE_END);
if (__builtin_expect( (r->conf.log_state_handling), 0))
connection_state_machine_loop(r, con);
}
}
else if (dlen) /*(do not spin if swin empty window)*/
resched |= 1; /*(!chunkqueue_is_empty(&r->write_queue))*/
}
#if 0