diff --git a/mongoose.c b/mongoose.c index 99d8072e..65cf7076 100644 --- a/mongoose.c +++ b/mongoose.c @@ -1344,6 +1344,7 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm, status, mg_http_status_code_str(status), (int) mime.len, mime.ptr, etag, cl, range, opts->extra_headers ? opts->extra_headers : ""); if (mg_vcasecmp(&hm->method, "HEAD") == 0) { + c->is_draining = 1; fs->close(fd); } else { c->pfn = static_cb; @@ -3091,23 +3092,24 @@ static void write_conn(struct mg_connection *c) { } static void close_conn(struct mg_connection *c) { - // Unlink this connection from the list - mg_resolve_cancel(c); + mg_resolve_cancel(c); // Close any pending DNS query LIST_DELETE(struct mg_connection, &c->mgr->conns, c); if (c == c->mgr->dns4.c) c->mgr->dns4.c = NULL; if (c == c->mgr->dns6.c) c->mgr->dns6.c = NULL; + // Order of operations is important. `MG_EV_CLOSE` event must be fired + // before we deallocate received data, see #1331 mg_call(c, MG_EV_CLOSE, NULL); - // while (c->callbacks != NULL) mg_fn_del(c, c->callbacks->fn); LOG(LL_DEBUG, ("%lu closed", c->id)); if (FD(c) != INVALID_SOCKET) { closesocket(FD(c)); #if MG_ARCH == MG_ARCH_FREERTOS_TCP FreeRTOS_FD_CLR(c->fd, c->mgr->ss, eSELECT_ALL); #endif + c->fd = S2PTR(INVALID_SOCKET); } mg_tls_free(c); - free(c->recv.buf); - free(c->send.buf); + mg_iobuf_free(&c->recv); + mg_iobuf_free(&c->send); memset(c, 0, sizeof(*c)); free(c); } diff --git a/src/http.c b/src/http.c index dfc30827..c9be9ef4 100644 --- a/src/http.c +++ b/src/http.c @@ -573,6 +573,7 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm, status, mg_http_status_code_str(status), (int) mime.len, mime.ptr, etag, cl, range, opts->extra_headers ? opts->extra_headers : ""); if (mg_vcasecmp(&hm->method, "HEAD") == 0) { + c->is_draining = 1; fs->close(fd); } else { c->pfn = static_cb; diff --git a/src/sock.c b/src/sock.c index 255f6ad1..4fda912d 100644 --- a/src/sock.c +++ b/src/sock.c @@ -265,23 +265,24 @@ static void write_conn(struct mg_connection *c) { } static void close_conn(struct mg_connection *c) { - // Unlink this connection from the list - mg_resolve_cancel(c); + mg_resolve_cancel(c); // Close any pending DNS query LIST_DELETE(struct mg_connection, &c->mgr->conns, c); if (c == c->mgr->dns4.c) c->mgr->dns4.c = NULL; if (c == c->mgr->dns6.c) c->mgr->dns6.c = NULL; + // Order of operations is important. `MG_EV_CLOSE` event must be fired + // before we deallocate received data, see #1331 mg_call(c, MG_EV_CLOSE, NULL); - // while (c->callbacks != NULL) mg_fn_del(c, c->callbacks->fn); LOG(LL_DEBUG, ("%lu closed", c->id)); if (FD(c) != INVALID_SOCKET) { closesocket(FD(c)); #if MG_ARCH == MG_ARCH_FREERTOS_TCP FreeRTOS_FD_CLR(c->fd, c->mgr->ss, eSELECT_ALL); #endif + c->fd = S2PTR(INVALID_SOCKET); } mg_tls_free(c); - free(c->recv.buf); - free(c->send.buf); + mg_iobuf_free(&c->recv); + mg_iobuf_free(&c->send); memset(c, 0, sizeof(*c)); free(c); }