From 1329f70516e23475830ee9575e301991392c4e73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20de=20Giessen?= Date: Thu, 10 Jul 2025 11:05:19 +0200 Subject: [PATCH 1/3] esp32/network_ppp: Use thread-safe API for PPPoS input. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A small follow-up to 3b1e22c66947271e8b60eddf4e8aa6dadc6d9a7d, in which the entire PPP implementation was reworked to more closely resemble the extmod version. One of the differences between extmod and the ESP32 port is that the ESP32 port uses the thread-safe API, but in that changeset the PPP input function was accidentally changed to use the non-safe API. Signed-off-by: Daniël van de Giessen --- ports/esp32/network_ppp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/network_ppp.c b/ports/esp32/network_ppp.c index 8b700c98ef386..77e4385ca1ee1 100644 --- a/ports/esp32/network_ppp.c +++ b/ports/esp32/network_ppp.c @@ -163,7 +163,7 @@ static mp_obj_t network_ppp_poll(size_t n_args, const mp_obj_t *args) { } mp_printf(&mp_plat_print, ")\n"); #endif - pppos_input(self->pcb, (u8_t *)buf, len); + pppos_input_tcpip(self->pcb, (u8_t *)buf, len); total_len += len; } From efb9ec29ada44e343c734db76208bbb60ca2aea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20de=20Giessen?= Date: Thu, 10 Jul 2025 14:43:29 +0200 Subject: [PATCH 2/3] esp32/network_ppp: Use non-thread-safe API inside status callback. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The status callback runs on the lwIP tcpip_thread, and thus must use the non-thread-safe API because the thread-safe API would cause a deadlock. Signed-off-by: Daniël van de Giessen --- extmod/network_ppp_lwip.c | 8 +++++--- ports/esp32/network_ppp.c | 11 ++++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/extmod/network_ppp_lwip.c b/extmod/network_ppp_lwip.c index 2c3dac92012a0..883275f48196b 100644 --- a/extmod/network_ppp_lwip.c +++ b/extmod/network_ppp_lwip.c @@ -62,8 +62,6 @@ typedef struct _network_ppp_obj_t { const mp_obj_type_t mp_network_ppp_lwip_type; -static mp_obj_t network_ppp___del__(mp_obj_t self_in); - static void network_ppp_stream_uart_irq_disable(network_ppp_obj_t *self) { if (self->stream == mp_const_none) { return; @@ -88,8 +86,12 @@ static void network_ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) { // only need to free the PPP PCB, not close it. self->state = STATE_ACTIVE; } + network_ppp_stream_uart_irq_disable(self); // Clean up the PPP PCB. - network_ppp___del__(MP_OBJ_FROM_PTR(self)); + if (ppp_free(pcb) == ERR_OK) { + self->state = STATE_INACTIVE; + self->pcb = NULL; + } break; default: self->state = STATE_ERROR; diff --git a/ports/esp32/network_ppp.c b/ports/esp32/network_ppp.c index 77e4385ca1ee1..3a9cb239db893 100644 --- a/ports/esp32/network_ppp.c +++ b/ports/esp32/network_ppp.c @@ -68,8 +68,6 @@ typedef struct _network_ppp_obj_t { const mp_obj_type_t esp_network_ppp_lwip_type; -static mp_obj_t network_ppp___del__(mp_obj_t self_in); - static void network_ppp_stream_uart_irq_disable(network_ppp_obj_t *self) { if (self->stream == mp_const_none) { return; @@ -94,8 +92,15 @@ static void network_ppp_status_cb(ppp_pcb *pcb, int err_code, void *ctx) { // only need to free the PPP PCB, not close it. self->state = STATE_ACTIVE; } + network_ppp_stream_uart_irq_disable(self); // Clean up the PPP PCB. - network_ppp___del__(MP_OBJ_FROM_PTR(self)); + // Note: Because we use pppapi_close instead of ppp_close, this + // callback will run on the lwIP tcpip_thread, thus to prevent a + // deadlock we must use the non-threadsafe function here. + if (ppp_free(pcb) == ERR_OK) { + self->state = STATE_INACTIVE; + self->pcb = NULL; + } break; default: self->state = STATE_ERROR; From c0717d59c5ab10a1c84a4c45b15e60ddf3e4d3c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20de=20Giessen?= Date: Tue, 8 Jul 2025 15:52:17 +0200 Subject: [PATCH 3/3] esp32/network_ppp: Correctly clean up PPP PCB after close. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If PPP is still connected, freeing the PCB will fail and thus instead we should trigger a disconnect and wait for the lwIP callback to actually free the PCB. When PPP is not connected we should check if the freeing failed, warn the user if so, and only mark the connection as inactive if not. When all this happens during garbage collection the best case is that the PPP connection is already dead, which means the callback will be called immediately and cleanup will happen correctly. The worst case is that the connection is still alive, thus we are unable to free the PCB (lwIP won't let us) and it remains referenced in the netif_list, meaning a use-after-free happens later when lwIP traverses that linked list. This change does not fully prevent that, but it *does* improve how the PPP.active(False) method on the ESP32 port behaves: It no longer immediately tries to free (and fails), but instead triggers a disconnect and lets the cleanup happen correctly through the status callback. Signed-off-by: Daniël van de Giessen --- extmod/network_ppp_lwip.c | 19 ++++++++++--------- ports/esp32/network_ppp.c | 18 +++++++++--------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/extmod/network_ppp_lwip.c b/extmod/network_ppp_lwip.c index 883275f48196b..12205521f670f 100644 --- a/extmod/network_ppp_lwip.c +++ b/extmod/network_ppp_lwip.c @@ -119,17 +119,18 @@ static mp_obj_t network_ppp_make_new(const mp_obj_type_t *type, size_t n_args, s static mp_obj_t network_ppp___del__(mp_obj_t self_in) { network_ppp_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self->state >= STATE_ACTIVE) { - if (self->state >= STATE_ERROR) { - // Still connected over the stream. - // Force the connection to close, with nocarrier=1. - self->state = STATE_INACTIVE; - ppp_close(self->pcb, 1); - } - network_ppp_stream_uart_irq_disable(self); + + network_ppp_stream_uart_irq_disable(self); + if (self->state >= STATE_ERROR) { + // Still connected over the stream. + // Force the connection to close, with nocarrier=1. + ppp_close(self->pcb, 1); + } else if (self->state >= STATE_ACTIVE) { // Free PPP PCB and reset state. + if (ppp_free(self->pcb) != ERR_OK) { + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("ppp_free failed")); + } self->state = STATE_INACTIVE; - ppp_free(self->pcb); self->pcb = NULL; } return mp_const_none; diff --git a/ports/esp32/network_ppp.c b/ports/esp32/network_ppp.c index 3a9cb239db893..18e0c8816889a 100644 --- a/ports/esp32/network_ppp.c +++ b/ports/esp32/network_ppp.c @@ -128,17 +128,17 @@ static mp_obj_t network_ppp_make_new(const mp_obj_type_t *type, size_t n_args, s static mp_obj_t network_ppp___del__(mp_obj_t self_in) { network_ppp_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self->state >= STATE_ACTIVE) { - if (self->state >= STATE_ERROR) { - // Still connected over the stream. - // Force the connection to close, with nocarrier=1. - self->state = STATE_INACTIVE; - pppapi_close(self->pcb, 1); - } - network_ppp_stream_uart_irq_disable(self); + network_ppp_stream_uart_irq_disable(self); + if (self->state >= STATE_ERROR) { + // Still connected over the stream. + // Force the connection to close, with nocarrier=1. + pppapi_close(self->pcb, 1); + } else if (self->state >= STATE_ACTIVE) { // Free PPP PCB and reset state. + if (pppapi_free(self->pcb) != ERR_OK) { + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("pppapi_free failed")); + } self->state = STATE_INACTIVE; - pppapi_free(self->pcb); self->pcb = NULL; } return mp_const_none; pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy