diff --git a/mongoose.c b/mongoose.c index 82aebae8751809666dd4c41ed47e7f5a2d3d4675..f19033d864a8a8dbe38ca464deec597a01548b98 100644 --- a/mongoose.c +++ b/mongoose.c @@ -2466,6 +2466,11 @@ void mg_close_conn(struct mg_connection *conn) { mg_ssl_if_conn_close_notify(conn); } #endif + /* + * Clearly mark the connection as going away (if not already). + * Some net_if impls (LwIP) need this for cleanly handling half-dead conns. + */ + conn->flags |= MG_F_CLOSE_IMMEDIATELY; mg_remove_conn(conn); conn->iface->vtable->destroy_conn(conn); mg_call(conn, NULL, conn->user_data, MG_EV_CLOSE, NULL); @@ -14901,7 +14906,7 @@ static err_t mg_lwip_tcp_conn_cb(void *arg, struct tcp_pcb *tpcb, err_t err) { static void mg_lwip_tcp_error_cb(void *arg, err_t err) { struct mg_connection *nc = (struct mg_connection *) arg; DBG(("%p conn error %d", nc, err)); - if (nc == NULL) return; + if (nc == NULL || (nc->flags & MG_F_CLOSE_IMMEDIATELY)) return; struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; cs->pcb.tcp = NULL; /* Has already been deallocated */ if (nc->flags & MG_F_CONNECTING) { @@ -15538,10 +15543,11 @@ void mg_ev_mgr_lwip_process_signals(struct mg_mgr *mgr) { (struct mg_ev_mgr_lwip_data *) mgr->ifaces[MG_MAIN_IFACE]->data; while (md->sig_queue_len > 0) { mgos_lock(); - int sig = md->sig_queue[md->start_index].sig; - struct mg_connection *nc = md->sig_queue[md->start_index].nc; + int i = md->start_index; + int sig = md->sig_queue[i].sig; + struct mg_connection *nc = md->sig_queue[i].nc; struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; - md->start_index = (md->start_index + 1) % MG_SIG_QUEUE_LEN; + md->start_index = (i + 1) % MG_SIG_QUEUE_LEN; md->sig_queue_len--; mgos_unlock(); if (nc->iface == NULL || nc->mgr == NULL) continue; diff --git a/src/common/platforms/lwip/mg_lwip_ev_mgr.c b/src/common/platforms/lwip/mg_lwip_ev_mgr.c index 1e844a8237ce566c9ff6ed2966207c0873242251..39937fc919b01673747b9a68da2666f9c617f1e0 100644 --- a/src/common/platforms/lwip/mg_lwip_ev_mgr.c +++ b/src/common/platforms/lwip/mg_lwip_ev_mgr.c @@ -53,10 +53,11 @@ void mg_ev_mgr_lwip_process_signals(struct mg_mgr *mgr) { (struct mg_ev_mgr_lwip_data *) mgr->ifaces[MG_MAIN_IFACE]->data; while (md->sig_queue_len > 0) { mgos_lock(); - int sig = md->sig_queue[md->start_index].sig; - struct mg_connection *nc = md->sig_queue[md->start_index].nc; + int i = md->start_index; + int sig = md->sig_queue[i].sig; + struct mg_connection *nc = md->sig_queue[i].nc; struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; - md->start_index = (md->start_index + 1) % MG_SIG_QUEUE_LEN; + md->start_index = (i + 1) % MG_SIG_QUEUE_LEN; md->sig_queue_len--; mgos_unlock(); if (nc->iface == NULL || nc->mgr == NULL) continue; diff --git a/src/common/platforms/lwip/mg_lwip_net_if.c b/src/common/platforms/lwip/mg_lwip_net_if.c index f73f607a282e7ab346003bb2bdd56dcaba5c171d..2090fca35576a74bf5d0e511c7e342e02d8dd85e 100644 --- a/src/common/platforms/lwip/mg_lwip_net_if.c +++ b/src/common/platforms/lwip/mg_lwip_net_if.c @@ -126,7 +126,7 @@ static err_t mg_lwip_tcp_conn_cb(void *arg, struct tcp_pcb *tpcb, err_t err) { static void mg_lwip_tcp_error_cb(void *arg, err_t err) { struct mg_connection *nc = (struct mg_connection *) arg; DBG(("%p conn error %d", nc, err)); - if (nc == NULL) return; + if (nc == NULL || (nc->flags & MG_F_CLOSE_IMMEDIATELY)) return; struct mg_lwip_conn_state *cs = (struct mg_lwip_conn_state *) nc->sock; cs->pcb.tcp = NULL; /* Has already been deallocated */ if (nc->flags & MG_F_CONNECTING) { diff --git a/src/mg_net.c b/src/mg_net.c index 050ac791b8992b965e3a38c6a3a9bddf7a1ab82d..ad9a8fb0887a79cbbc7cc5c5615ec71d36a4cf3a 100644 --- a/src/mg_net.c +++ b/src/mg_net.c @@ -176,6 +176,11 @@ void mg_close_conn(struct mg_connection *conn) { mg_ssl_if_conn_close_notify(conn); } #endif + /* + * Clearly mark the connection as going away (if not already). + * Some net_if impls (LwIP) need this for cleanly handling half-dead conns. + */ + conn->flags |= MG_F_CLOSE_IMMEDIATELY; mg_remove_conn(conn); conn->iface->vtable->destroy_conn(conn); mg_call(conn, NULL, conn->user_data, MG_EV_CLOSE, NULL);