From 60a320467a78171fdfe241052d55ba0a89dfadbb Mon Sep 17 00:00:00 2001 From: meganetaaan <1918755+meganetaaan@users.noreply.github.com> Date: Fri, 14 Aug 2026 22:50:13 +0900 Subject: [PATCH] fix lwIP TCP receive lifetime --- modules/io/socket/lwip/tcp.c | 9 ++++----- modules/network/socket/lwip/modLwipSafe.c | 24 +++++++++++++---------- modules/network/socket/lwip/modLwipSafe.h | 4 ++-- modules/network/socket/lwip/modSocket.c | 6 ++---- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/modules/io/socket/lwip/tcp.c b/modules/io/socket/lwip/tcp.c index ba206e2cc..6a0d4fad0 100644 --- a/modules/io/socket/lwip/tcp.c +++ b/modules/io/socket/lwip/tcp.c @@ -369,7 +369,7 @@ void xs_tcp_read(xsMachine *the) builtinCriticalSectionBegin(); tcp->buffers = buffer->next; builtinCriticalSectionEnd(); - tcp_recved_safe(tcp->skt, buffer->pb->tot_len); + tcp_recved_safe(&tcp->skt, buffer->pb->tot_len); pbuf_free_safe(buffer->pb); c_free(buffer); if (NULL == tcp->buffers) { @@ -566,10 +566,9 @@ err_t tcpReceive(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, err_t err) } if ((NULL == pb) || (ERR_OK != err)) { //@@ when is err set here? - removeTCPCallbacks(tcp); -#if ESP32 -//@@ tcp->skt = NULL; // no close on socket if disconnected. -#endif + tcp_recv(pcb, NULL); + tcp_sent(pcb, NULL); + tcp->triggerable &= ~kTCPWritable; tcpTrigger(tcp, kTCPError); return ERR_OK; } diff --git a/modules/network/socket/lwip/modLwipSafe.c b/modules/network/socket/lwip/modLwipSafe.c index 0451fb687..0350d2277 100644 --- a/modules/network/socket/lwip/modLwipSafe.c +++ b/modules/network/socket/lwip/modLwipSafe.c @@ -29,6 +29,7 @@ typedef struct { err_t err; struct tcp_pcb *tcpPCB; + struct tcp_pcb **tcpPCBRef; struct udp_pcb *udpPCB; ip_addr_t *ipaddr; ip_addr_t addr; @@ -174,19 +175,23 @@ err_t tcp_write_safe(struct tcp_pcb *tcpPCB, const void *data, u16_t len, u8_t f return msg.err; } -static void tcp_recved_INLWIP(void *ctx) +static err_t tcp_recved_INLWIP(struct tcpip_api_call_data *tcpMsg) { - LwipMsg msg = (LwipMsg)ctx; - tcp_recved(msg->tcpPCB, msg->len); - c_free(msg); + LwipMsg msg = (LwipMsg)tcpMsg; + if (*msg->tcpPCBRef) + tcp_recved(*msg->tcpPCBRef, msg->len); + return ERR_OK; } -void tcp_recved_safe(struct tcp_pcb *tcpPCB, u16_t len) +void tcp_recved_safe(struct tcp_pcb **tcpPCBRef, u16_t len) { - LwipMsg msg = c_malloc(sizeof(LwipMsgRecord)); - msg->tcpPCB = tcpPCB; - msg->len = len; - tcpip_callback_with_block(tcp_recved_INLWIP, msg, 1); + LwipMsgRecord msg = { + .tcpPCBRef = tcpPCBRef, + .len = len, + }; + // Re-read the PCB after earlier queued network events have run. The owner + // stays alive because tcpip_api_call does not return until this completes. + tcpip_api_call(tcp_recved_INLWIP, &msg.call); } static err_t tcp_listen_INLWIP(struct tcpip_api_call_data *tcpMsg) @@ -294,4 +299,3 @@ err_t dns_gethostbyname_safe(const char *hostname, ip_addr_t *addr, dns_found_ca } #endif - diff --git a/modules/network/socket/lwip/modLwipSafe.h b/modules/network/socket/lwip/modLwipSafe.h index f3951a890..5501550af 100644 --- a/modules/network/socket/lwip/modLwipSafe.h +++ b/modules/network/socket/lwip/modLwipSafe.h @@ -34,7 +34,7 @@ #define tcp_clear_callbacks_safe(pb) {tcp_arg(pb, NULL); tcp_recv(pb, NULL); tcp_sent(pb, NULL); tcp_err(pb, NULL);} #define tcp_output_safe tcp_output #define tcp_write_safe tcp_write - #define tcp_recved_safe(skt, len) tcp_recved(skt, len) + #define tcp_recved_safe(skt, len) {if (*(skt)) tcp_recved(*(skt), len);} #define udp_new_safe udp_new #define udp_bind_safe udp_bind #define udp_remove_safe udp_remove @@ -61,7 +61,7 @@ void tcp_close_safe(struct tcp_pcb *tcpPCB); void tcp_output_safe(struct tcp_pcb *tcpPCB); err_t tcp_write_safe(struct tcp_pcb *tcpPCB, const void *data, u16_t len, u8_t flags); - void tcp_recved_safe(struct tcp_pcb *tcpPCB, u16_t len); + void tcp_recved_safe(struct tcp_pcb **tcpPCBRef, u16_t len); struct tcp_pcb * tcp_listen_safe(struct tcp_pcb *pcb); struct udp_pcb *udp_new_safe(void); err_t udp_bind_safe(struct udp_pcb *udpPCB, const ip_addr_t *ipaddr, u16_t port); diff --git a/modules/network/socket/lwip/modSocket.c b/modules/network/socket/lwip/modSocket.c index ee1c6f4fe..676166998 100644 --- a/modules/network/socket/lwip/modSocket.c +++ b/modules/network/socket/lwip/modSocket.c @@ -586,7 +586,7 @@ void xs_socket_read(xsMachine *the) socketSetPending(xss, kPendingReceive); else { if ((kTCP == xss->kind) && xss->skt) - tcp_recved_safe(xss->skt, xss->pb->tot_len); + tcp_recved_safe(&xss->skt, xss->pb->tot_len); pbuf_free_safe(xss->pb); xss->pb = NULL; @@ -860,7 +860,7 @@ void socketMsgDataReceived(xsSocket xss) } if ((kTCP == xss->kind) && xss->skt) //@@ - tcp_recved_safe(xss->skt, xss->pb->tot_len); + tcp_recved_safe(&xss->skt, xss->pb->tot_len); pbuf_free_safe(xss->pb); xss->pb = NULL; @@ -1010,7 +1010,6 @@ err_t didReceive(void * arg, struct tcp_pcb * pcb, struct pbuf * p, err_t err) if (!p) { // connnection closed tcp_recv(xss->skt, NULL); tcp_sent(xss->skt, NULL); - tcp_err(xss->skt, NULL); if (xss->reader[0] || xss->buflen) xss->disconnectedWhileReading = true; @@ -1364,4 +1363,3 @@ void *modSocketGetLWIP(xsMachine *the, xsSlot *slot) } return skt; } -