diff --git a/src/httpterm.c b/src/httpterm.c index 6ba2ffb62..9bc83fd5a 100644 --- a/src/httpterm.c +++ b/src/httpterm.c @@ -438,12 +438,14 @@ static int hstream_htx_buf_rcv(struct connection *conn, struct hstream *hs) TRACE_ENTER(HS_EV_HSTRM_RECV, hs); if (hs->sc->wait_event.events & SUB_RETRY_RECV) { - TRACE_DEVEL("waiting for data", HS_EV_HSTRM_RECV, hs); + TRACE_DEVEL("subscribed for RECV, waiting for data", HS_EV_HSTRM_RECV, hs); goto wait_more_data; } - if (sc_ep_test(hs->sc, SE_FL_EOS)) + if (sc_ep_test(hs->sc, SE_FL_EOS)) { + TRACE_STATE("end of stream", HS_EV_HSTRM_RECV, hs); goto end_recv; + } if (hs->flags & HS_ST_IN_ALLOC) { TRACE_STATE("waiting for input buffer", HS_EV_HSTRM_RECV, hs); @@ -496,7 +498,8 @@ static int hstream_htx_buf_rcv(struct connection *conn, struct hstream *hs) leave: hstream_release_buf(hs, &hs->req); TRACE_PRINTF(TRACE_LEVEL_PROTO, HS_EV_HSTRM_RECV, hs, 0, 0, 0, - "data received (%llu) ret=%d read=%d", (unsigned long long)cur_read, ret, (int)read); + "data received (%llu) ret=%d read=%d fin=%d", + (unsigned long long)cur_read, ret, (int)read, fin); TRACE_LEAVE(HS_EV_HSTRM_RECV, hs); return ret; stop: @@ -934,7 +937,16 @@ static inline int hstream_must_rcv(struct hstream *hs) int ret; TRACE_ENTER(HS_EV_PROCESS_HSTRM, hs); - ret = hs->req_body > 0 && +#if 0 + fprintf(stderr, "%s %d && %d && %d && (%d || (%d && %d))\n", __func__, + hs->req_body > 0, + !(hs->flags & HS_ST_CONN_ERROR), + !(hs->sc->wait_event.events & SUB_RETRY_RECV), + !hs->req_after_res, + !hs->to_write, + htx_is_empty(htxbuf(&hs->res))); +#endif + ret = hs->req_body > 0 && !(hs->flags & HS_ST_CONN_ERROR) && (!hs->req_after_res || (!hs->to_write && htx_is_empty(htxbuf(&hs->res)))); TRACE_LEAVE(HS_EV_PROCESS_HSTRM, hs); @@ -993,8 +1005,11 @@ static struct task *process_hstream(struct task *t, void *context, unsigned int TRACE_STATE("no more expected data", HS_EV_HSTRM_RESP, hs); hs->req_body = 0; } - else if (hstream_must_rcv(hs)) { - /* The body will be drained upon next wakeup */ + + if (hstream_must_rcv(hs)) { + /* The request must be drained before sending the response (hs->req_after_res=0). + * The body will be drained upon next wakeup. + */ TRACE_STATE("waking up task", HS_EV_HSTRM_IO_CB, hs); task_wakeup(hs->task, TASK_WOKEN_IO); goto out; @@ -1055,6 +1070,14 @@ static struct task *process_hstream(struct task *t, void *context, unsigned int TRACE_DEVEL("shutting down stream", HS_EV_HSTRM_SEND, hs); conn->mux->shut(hs->sc, SE_SHW_SILENT|SE_SHW_NORMAL, NULL); } + else if (hstream_must_rcv(hs) && !(hs->sc->wait_event.events & SUB_RETRY_RECV)) { + /* The request must be drained before sending the response (hs->req_after_res=0). + * The body will be drained upon next wakeup. + */ + TRACE_STATE("waking up task", HS_EV_HSTRM_IO_CB, hs); + task_wakeup(hs->task, TASK_WOKEN_IO); + goto leave; + } if (hs->flags & HS_ST_CONN_ERROR || (!hs->to_write && !hs->req_body && htx_is_empty(htxbuf(&hs->res)))) {