diff --git a/lib/context.c b/lib/context.c index 7d76c803..e11af453 100644 --- a/lib/context.c +++ b/lib/context.c @@ -246,9 +246,14 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, case LWS_CALLBACK_HTTP_WRITEABLE: #ifdef LWS_WITH_CGI - if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI) { - if (lws_cgi_write_split_stdout_headers(wsi) < 0) + if (wsi->reason_bf & (LWS_CB_REASON_AUX_BF__CGI_HEADERS | LWS_CB_REASON_AUX_BF__CGI)) { + n = lws_cgi_write_split_stdout_headers(wsi); + if (n < 0) { + lwsl_debug("LWS_CB_REASON_AUX_BF__CGI forcing close\n"); return -1; + } + if (!n) + lws_rx_flow_control(wsi->cgi->stdwsi[LWS_STDOUT], 1); if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI_HEADERS) wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__CGI_HEADERS; @@ -258,6 +263,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, } if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI_CHUNK_END) { + lwsl_debug("writing chunk terminator and exiting\n"); n = lws_write(wsi, (unsigned char *)"0\x0d\x0a\x0d\x0a", 5, LWS_WRITE_HTTP); /* always close after sending it */ @@ -363,6 +369,8 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, /* TBD stdin rx flow control */ break; case LWS_STDOUT: + /* quench POLLIN on STDOUT until MASTER got writeable */ + lws_rx_flow_control(args->stdwsi[LWS_STDOUT], 0); wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI; /* when writing to MASTER would not block */ lws_callback_on_writable(wsi); @@ -385,6 +393,7 @@ lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason, wsi->cgi->explicitly_chunked, (uint64_t)wsi->cgi->content_length); if (!wsi->cgi->explicitly_chunked && !wsi->cgi->content_length) { /* send terminating chunk */ + lwsl_debug("LWS_CALLBACK_CGI_TERMINATED: looking to send terminating chunk\n"); wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_CHUNK_END; lws_callback_on_writable(wsi); lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, 3); diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index 32b27325..3ce469f0 100755 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -3028,8 +3028,13 @@ lws_cgi_write_split_stdout_headers(struct lws *wsi) return -1; } wsi->cgi->content_length_seen += m; + } else { + if (wsi->cgi_stdout_zero_length) { + lwsl_debug("%s: failed to read anything: stdout is POLLHUP'd\n", __func__); + return 1; + } + wsi->cgi_stdout_zero_length = 1; } - return 0; } @@ -3153,7 +3158,7 @@ lws_cgi_kill_terminated(struct lws_context_per_thread *pt) if (!cgi->content_length) { /* - * well, if he sends chunked... give him 5s after the + * well, if he sends chunked... give him 2s after the * cgi terminated to send buffered */ cgi->chunked_grace++; @@ -3192,7 +3197,7 @@ lws_cgi_kill_terminated(struct lws_context_per_thread *pt) /* we deferred killing him after reaping his PID */ if (cgi->chunked_grace) { cgi->chunked_grace++; - if (cgi->chunked_grace < 5) + if (cgi->chunked_grace < 2) continue; goto finish_him; } @@ -3214,7 +3219,7 @@ lws_cgi_kill_terminated(struct lws_context_per_thread *pt) if (!cgi->content_length) { /* - * well, if he sends chunked... give him 5s after the + * well, if he sends chunked... give him 2s after the * cgi terminated to send buffered */ cgi->chunked_grace++; diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 5c75bed6..ee2edd36 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -1671,6 +1671,7 @@ struct lws { unsigned int ipv6:1; unsigned int parent_carries_io:1; unsigned int parent_pending_cb_on_writable:1; + unsigned int cgi_stdout_zero_length:1; #if defined(LWS_WITH_ESP8266) unsigned int pending_send_completion:3; diff --git a/lib/service.c b/lib/service.c index 1850426a..184ded08 100644 --- a/lib/service.c +++ b/lib/service.c @@ -902,7 +902,7 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t wsi, buf, pt->ah_pool[n].rxpos, pt->ah_pool[n].rxlen, pt->ah_pool[n].pos); - + buf[0] = '\0'; m = 0; do { c = lws_token_to_string(m); @@ -915,11 +915,12 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, int t continue; } - lws_hdr_copy(wsi, buf, sizeof buf, m); - buf[sizeof(buf) - 1] = '\0'; + if (lws_hdr_copy(wsi, buf, sizeof buf, m) > 0) { + buf[sizeof(buf) - 1] = '\0'; - lwsl_notice(" %s = %s\n", - (const char *)c, buf); + lwsl_notice(" %s = %s\n", + (const char *)c, buf); + } m++; } while (1);