From 360c0a8ee4e30f80ebb7c2b3370caba231512e15 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Sun, 28 Feb 2016 11:02:42 +0800 Subject: [PATCH] ah move more_rx_waiting to wsi scope Originally this was alright in wsi->u.hdr, because ah implied header processing. But since we allowed ah to be held across http keep-alive transactions if we saw we had more header data, it means we were trying to read this union member out of scope after it had transitioned. Moving the more_rx_waiting member to be a 1-bit bifield in the wsi solves it and lets us check the state any time later at http transaction completion. https://github.com/warmcat/libwebsockets/issues/441 Signed-off-by: Andy Green --- changelog | 6 ++++++ lib/parsers.c | 2 +- lib/private-libwebsockets.h | 2 +- lib/server.c | 11 ++++++++--- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/changelog b/changelog index 2e99106..f8e9288 100644 --- a/changelog +++ b/changelog @@ -7,6 +7,12 @@ Fixes 1) MAJOR connections on ah waiting list that closed did not get removed from the waiting list... +2) MAJOR since we added the ability to hold an ah across http keepalive +transactions where more headers had already arrived, we broke the ability +to tell if more headers had arrived. Result was if the browser didn't +close the keepalive, we retained ah for the lifetime of the keepalive, +using up the pool. + v1.7.2 ====== diff --git a/lib/parsers.c b/lib/parsers.c index 0dee8ca..360e261 100644 --- a/lib/parsers.c +++ b/lib/parsers.c @@ -216,7 +216,7 @@ int lws_header_table_detach(struct lws *wsi) "wsi->more_rx_waiting %d\n", __func__, wsi, (int)(now - wsi->u.hdr.ah->assigned), ah->rxpos, ah->rxlen, wsi->mode, wsi->state, - wsi->u.hdr.more_rx_waiting); + wsi->more_rx_waiting); } /* if we think we're detaching one, there should be one in use */ diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index af62e8f..9c3609a 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -948,7 +948,6 @@ struct _lws_header_related { char post_literal_equal; unsigned char parser_state; /* enum lws_token_indexes */ char redirects; - char more_rx_waiting; }; struct _lws_websocket_related { @@ -1056,6 +1055,7 @@ struct lws { unsigned int user_space_externally_allocated:1; unsigned int socket_is_permanently_unusable:1; unsigned int rxflow_change_to:2; + unsigned int more_rx_waiting:1; /* has to live here since ah may stick to end */ #ifndef LWS_NO_EXTENSIONS unsigned int extension_data_pending:1; #endif diff --git a/lib/server.c b/lib/server.c index 1d044ff..5ab695e 100644 --- a/lib/server.c +++ b/lib/server.c @@ -352,7 +352,7 @@ lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len) assert(wsi->u.hdr.ah); while (len--) { - wsi->u.hdr.more_rx_waiting = !!len; + wsi->more_rx_waiting = !!len; assert(wsi->mode == LWSCM_HTTP_SERVING); @@ -364,7 +364,9 @@ lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len) if (wsi->u.hdr.parser_state != WSI_PARSING_COMPLETE) continue; - lwsl_parser("lws_parse sees parsing complete\n"); + lwsl_parser("%s: lws_parse sees parsing complete\n", __func__); + lwsl_debug("%s: wsi->more_rx_waiting=%d\n", __func__, + wsi->more_rx_waiting); wsi->mode = LWSCM_PRE_WS_SERVING_ACCEPT; lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0); @@ -744,7 +746,10 @@ lws_http_transaction_completed(struct lws *wsi) * reset the existing header table and keep it. */ if (wsi->u.hdr.ah) { - if (!wsi->u.hdr.more_rx_waiting) { + lwsl_info("%s: wsi->more_rx_waiting=%d\n", __func__, + wsi->more_rx_waiting); + + if (!wsi->more_rx_waiting) { wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen; lws_header_table_detach(wsi); } else -- 2.7.4