From 923688d2da036f3cefc4fb494dcd770acaab1691 Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Tue, 14 Jun 2016 00:48:28 -0400 Subject: [PATCH] drain backend socket/pipe bufs upon FDEVENT_HUP (mod_cgi, mod_fastcgi, mod_scgi, mod_proxy) --- src/mod_cgi.c | 23 ++++++++++++++++------- src/mod_fastcgi.c | 19 +++++++++++-------- src/mod_proxy.c | 12 ++++++++++++ src/mod_scgi.c | 12 ++++++++++++ 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/mod_cgi.c b/src/mod_cgi.c index 456e6f87..4b1235d1 100644 --- a/src/mod_cgi.c +++ b/src/mod_cgi.c @@ -778,20 +778,29 @@ static handler_t cgi_handle_fdevent(server *srv, void *ctx, int revents) { /* perhaps this issue is already handled */ if (revents & FDEVENT_HUP) { - /* check if we still have a unfinished header package which is a body in reality */ - if (con->file_started == 0 && !buffer_string_is_empty(hctx->response_header)) { + if (con->file_started) { + /* drain any remaining data from kernel pipe buffers + * even if (con->conf.stream_response_body + * & FDEVENT_STREAM_RESPONSE_BUFMIN) + * since event loop will spin on fd FDEVENT_HUP event + * until unregistered. */ + handler_t rc; + do { + rc = cgi_recv_response(srv,hctx);/*(might invalidate hctx)*/ + } while (rc == HANDLER_GO_ON); /*(unless HANDLER_GO_ON)*/ + return rc; /* HANDLER_FINISHED or HANDLER_ERROR */ + } else if (!buffer_string_is_empty(hctx->response_header)) { + /* unfinished header package which is a body in reality */ con->file_started = 1; if (0 != http_chunk_append_buffer(srv, con, hctx->response_header)) { cgi_connection_close(srv, hctx); return HANDLER_ERROR; } - } - + } else { # if 0 - log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents); + log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents); # endif - - /* rtsigs didn't liked the close */ + } cgi_connection_close(srv, hctx); } else if (revents & FDEVENT_ERR) { /* kill all connections to the cgi process */ diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c index 48efd37a..8a132587 100644 --- a/src/mod_fastcgi.c +++ b/src/mod_fastcgi.c @@ -3407,14 +3407,17 @@ static handler_t fcgi_handle_fdevent(server *srv, void *ctx, int revents) { * */ fcgi_send_request(srv, hctx); - } else if (chunkqueue_is_empty(hctx->wb) && - hctx->wb->bytes_in != 0 && - hctx->proc->port == 0) { - /* FIXME: - * - * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket - * even if the FCGI_FIN packet is not received yet - */ + } else if (con->file_started) { + /* drain any remaining data from kernel pipe buffers + * even if (con->conf.stream_response_body + * & FDEVENT_STREAM_RESPONSE_BUFMIN) + * since event loop will spin on fd FDEVENT_HUP event + * until unregistered. */ + handler_t rc; + do { + rc = fcgi_recv_response(srv,hctx);/*(might invalidate hctx)*/ + } while (rc == HANDLER_GO_ON); /*(unless HANDLER_GO_ON)*/ + return rc; /* HANDLER_FINISHED or HANDLER_ERROR */ } else { fcgi_proc *proc = hctx->proc; log_error_write(srv, __FILE__, __LINE__, "sBSbsbsd", diff --git a/src/mod_proxy.c b/src/mod_proxy.c index 823bb5b2..90003689 100644 --- a/src/mod_proxy.c +++ b/src/mod_proxy.c @@ -855,6 +855,7 @@ static handler_t proxy_write_request(server *srv, handler_ctx *hctx) { if (hctx->wb->bytes_out == hctx->wb_reqlen) { fdevent_event_clr(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); + shutdown(hctx->fd, SHUT_WR);/* future: remove if HTTP/1.1 request */ proxy_set_state(srv, hctx, PROXY_STATE_READ); } else { off_t wblen = hctx->wb->bytes_in - hctx->wb->bytes_out; @@ -1117,6 +1118,17 @@ static handler_t proxy_handle_fdevent(server *srv, void *ctx, int revents) { proxy_connection_close(srv, hctx); con->http_status = 503; } + } else if (con->file_started) { + /* drain any remaining data from kernel pipe buffers + * even if (con->conf.stream_response_body + * & FDEVENT_STREAM_RESPONSE_BUFMIN) + * since event loop will spin on fd FDEVENT_HUP event + * until unregistered. */ + handler_t rc; + do { + rc = proxy_recv_response(srv,hctx);/*(might invalidate hctx)*/ + } while (rc == HANDLER_GO_ON); /*(unless HANDLER_GO_ON)*/ + return rc; /* HANDLER_FINISHED or HANDLER_ERROR */ } else { proxy_connection_close(srv, hctx); } diff --git a/src/mod_scgi.c b/src/mod_scgi.c index 72057f8c..00653bf4 100644 --- a/src/mod_scgi.c +++ b/src/mod_scgi.c @@ -2442,6 +2442,7 @@ static handler_t scgi_write_request(server *srv, handler_ctx *hctx) { if (hctx->wb->bytes_out == hctx->wb_reqlen) { fdevent_event_clr(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); + shutdown(hctx->fd, SHUT_WR); scgi_set_state(srv, hctx, FCGI_STATE_READ); } else { off_t wblen = hctx->wb->bytes_in - hctx->wb->bytes_out; @@ -2728,6 +2729,17 @@ static handler_t scgi_handle_fdevent(server *srv, void *ctx, int revents) { * */ scgi_send_request(srv, hctx); + } else if (con->file_started) { + /* drain any remaining data from kernel pipe buffers + * even if (con->conf.stream_response_body + * & FDEVENT_STREAM_RESPONSE_BUFMIN) + * since event loop will spin on fd FDEVENT_HUP event + * until unregistered. */ + handler_t rc; + do { + rc = scgi_recv_response(srv,hctx);/*(might invalidate hctx)*/ + } while (rc == HANDLER_GO_ON); /*(unless HANDLER_GO_ON)*/ + return rc; /* HANDLER_FINISHED or HANDLER_ERROR */ } else { scgi_extension_host *host= hctx->host; log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",