From 70034b58736f2fb262defcee9131852fc54d977d Mon Sep 17 00:00:00 2001 From: "Deomid \"rojer\" Ryabkov" Date: Sun, 13 Dec 2020 03:18:25 +0000 Subject: [PATCH] Fix stack overflow when serving http files on ESP8266 ESP8266 non-OS has very limited stack - only 4K. Undetected stack overflows cause nasty bugs and it turns out serving files over http routinely causes stack overflow. This was exposed by https://github.com/cesanta/mongoose-os/commit/a5f59123edcfef10c351b3e679f28720b5de9611 As a short-term workaround, push http_message into bss, this is enough as an immediate workaround. Longer term, we need to think how to bring 8266 to parity with other platforms where we have at least 8K stack. At the same time, get rid of the compiler bug workaround - modern toolchain doesn't need this. --- mongoose.c | 29 ++++++++--------------------- src/mg_http.c | 29 ++++++++--------------------- 2 files changed, 16 insertions(+), 42 deletions(-) diff --git a/mongoose.c b/mongoose.c index ebabcc05..a429c0e1 100644 --- a/mongoose.c +++ b/mongoose.c @@ -6395,30 +6395,17 @@ static void deliver_chunk(struct mg_connection *c, struct http_message *hm, } } -/* - * lx106 compiler has a bug (TODO(mkm) report and insert tracking bug here) - * If a big structure is declared in a big function, lx106 gcc will make it - * even bigger (round up to 4k, from 700 bytes of actual size). - */ -#ifdef __xtensa__ -static void mg_http_handler2(struct mg_connection *nc, int ev, - void *ev_data MG_UD_ARG(void *user_data), - struct http_message *hm) __attribute__((noinline)); - -void mg_http_handler(struct mg_connection *nc, int ev, - void *ev_data MG_UD_ARG(void *user_data)) { - struct http_message hm; - mg_http_handler2(nc, ev, ev_data MG_UD_ARG(user_data), &hm); -} - -static void mg_http_handler2(struct mg_connection *nc, int ev, - void *ev_data MG_UD_ARG(void *user_data), - struct http_message *hm) { -#else /* !__XTENSA__ */ void mg_http_handler(struct mg_connection *nc, int ev, void *ev_data MG_UD_ARG(void *user_data)) { +/* On ESP8266 stack is especially limited (4K). + * Since Mongoose is single-threaded, we can use the same struct + * and save ~400 bytes. This may not seem like much but in fact it's the + * difference between overflowing and not (when serving files). */ +#if CS_PLATFORM == CS_P_ESP8266 + static struct http_message shm, *hm = &shm; +#else struct http_message shm, *hm = &shm; -#endif /* __XTENSA__ */ +#endif struct mg_http_proto_data *pd = mg_http_get_proto_data(nc); struct mbuf *io = &nc->recv_mbuf; int req_len; diff --git a/src/mg_http.c b/src/mg_http.c index d16225f5..fb57d6a3 100644 --- a/src/mg_http.c +++ b/src/mg_http.c @@ -740,30 +740,17 @@ static void deliver_chunk(struct mg_connection *c, struct http_message *hm, } } -/* - * lx106 compiler has a bug (TODO(mkm) report and insert tracking bug here) - * If a big structure is declared in a big function, lx106 gcc will make it - * even bigger (round up to 4k, from 700 bytes of actual size). - */ -#ifdef __xtensa__ -static void mg_http_handler2(struct mg_connection *nc, int ev, - void *ev_data MG_UD_ARG(void *user_data), - struct http_message *hm) __attribute__((noinline)); - -void mg_http_handler(struct mg_connection *nc, int ev, - void *ev_data MG_UD_ARG(void *user_data)) { - struct http_message hm; - mg_http_handler2(nc, ev, ev_data MG_UD_ARG(user_data), &hm); -} - -static void mg_http_handler2(struct mg_connection *nc, int ev, - void *ev_data MG_UD_ARG(void *user_data), - struct http_message *hm) { -#else /* !__XTENSA__ */ void mg_http_handler(struct mg_connection *nc, int ev, void *ev_data MG_UD_ARG(void *user_data)) { +/* On ESP8266 stack is especially limited (4K). + * Since Mongoose is single-threaded, we can use the same struct + * and save ~400 bytes. This may not seem like much but in fact it's the + * difference between overflowing and not (when serving files). */ +#if CS_PLATFORM == CS_P_ESP8266 + static struct http_message shm, *hm = &shm; +#else struct http_message shm, *hm = &shm; -#endif /* __XTENSA__ */ +#endif struct mg_http_proto_data *pd = mg_http_get_proto_data(nc); struct mbuf *io = &nc->recv_mbuf; int req_len;