diff --git a/src/lwip_tcp/lwip_tcp.c b/src/lwip_tcp/lwip_tcp.c index 8f9bbca0..7e99488c 100644 --- a/src/lwip_tcp/lwip_tcp.c +++ b/src/lwip_tcp/lwip_tcp.c @@ -812,7 +812,15 @@ void tcp_slowtmr(struct lwip_tcp_ctx *ctx) } pcb2 = pcb; pcb = pcb->next; + int self_loop = (pcb == pcb2); + uint8_t sl_owner = pcb2->next_owner; tcp_free(pcb2); + if (self_loop) { + DEBUG_ERROR(DEBUG_CATEGORY_ALL, "TW_PCBS SELF-LOOP in tcp_slowtmr: freed pcb=%p state=TIME_WAIT port=%u next_owner=%d, clearing tw_pcbs", + (void*)pcb2, pcb2->local_port, sl_owner); + ctx->tw_pcbs = NULL; + break; + } } else { prev = pcb; pcb = pcb->next; @@ -1036,7 +1044,16 @@ static void tcp_kill_timewait(struct lwip_tcp_ctx *ctx) inactive = pcb; } } - if (inactive != NULL) tcp_abort(inactive); + if (inactive != NULL) { + if (inactive->next == inactive) { + DEBUG_ERROR(DEBUG_CATEGORY_ALL, "TW_PCBS SELF-LOOP in tcp_kill_timewait: aborting pcb=%p next_owner=%d, clearing tw_pcbs", + (void*)inactive, inactive->next_owner); + ctx->tw_pcbs = NULL; + tcp_free(inactive); + } else { + tcp_abort(inactive); + } + } } static void tcp_handle_closepend(struct lwip_tcp_ctx *ctx) diff --git a/src/lwip_tcp/lwip_tcp_in.c b/src/lwip_tcp/lwip_tcp_in.c index 044254b9..80b104df 100644 --- a/src/lwip_tcp/lwip_tcp_in.c +++ b/src/lwip_tcp/lwip_tcp_in.c @@ -221,7 +221,13 @@ void lwip_tcp_input(struct lwip_tcp_ctx *ctx, struct pbuf *p, pcb->local_port == dport && pcb->remote_ip == src_ip && pcb->local_ip == dst_ip) { - tcp_timewait_input(pcb); + if (pcb->next == pcb) { + DEBUG_ERROR(DEBUG_CATEGORY_ALL, "TW_PCBS SELF-LOOP in lwip_tcp_input: pcb=%p sport=%u dport=%u next_owner=%d, aborting", + (void*)pcb, sport, dport, pcb->next_owner); + tcp_abort(pcb); + } else { + tcp_timewait_input(pcb); + } pbuf_free(p); return; }