Hi,
I have traced the problem to calling tcp_close on a tcp_pcb which is
already in closed state.
I handle client disconnection roughly like this:

  if( tcp_write(client, ...); != ERR_OK) goto disconnect;
  // ...
  disconnect:
  tcp_close(client);

The problem is that when a client explicitly disconnects the PCB is
already in closed mode. A similar double-close bug has been mentioned
onlist by Dinesh Pandey on 29 Oct 2015 [1].
The workaround is simple. Check if pcb->state != CLOSED before calling
tcp_close.
I am now unable to trigger the looping pcbs situation in any
combination of opening and closing the connections, so I consider my
bug gone.

Happy hacking
KL

1: https://mail.gnu.org/archive/html/lwip-users/2015-10/msg00072.html

śr., 7 sty 2026 o 16:29 Krzysztof Lasocki <[email protected]> napisał(a):
>
> Hello,
>
> I am developing a simple datalogger using LwIP. I have a few sensor
> channels and I would like to have a separate TCP stream to stream data
> from them which i receive via telnet/netcat on the client side.
>
> I am trying to locate a bug which causes the LwIP stack to loop
> infinitely because the pcb linked list encounters a pcb which points
> to itself. Most strangely this is sometimes caught by the assert in
> tcp_input (tcp_in.c:269) and sometimes it is not, in those cases the
> for loop in tcp_in.c:251 is already infinitely looping.
>
> I noticed I can trigger this behavior while reconnecting to one TCP
> listener while the other TCP connection is established, but besides
> that I cannot locate the behavior.
>
> I have checked the following:
> - My software calls LwIP only from the main loop, I am using NO_SYS
> mode and callback api
> - The incoming packets are pulled out from a circular buffer which is
> filled by the PHY rx interrupt.
> - The RX interrupt is not calling any LwIP functions at all, and I did
> not notice any PCBs to have corrupted memory
> - I've made sure that the interrupt is not happening while
> board_netif.input function is called (Interrupts are disabled around
> it, and there is a data synchronization barrier inserted before it)
>
> I initialize the TCP listener with tcp_new_ip_type, tcp_arg, tcp_bind
> (upon reopen it returns ERR_USE - I am not sure what to do in that
> case), then tcp_listen and then set the callback with tcp_accept.
> The callback rejects multiple connections with ERR_USE. If this is the
> only connection it proceeds with saving the passed pcb. Later I use
> that pcb to send data with tcp_write and tcp_output.
> I've also tried closing the listener PCB in the accept callback but
> this does not seem to change anything
>
> I detect client disconnect by checking if tcp_write returned ERR_OK,
> if not, it means the client disconnected and I close both the
> connection and the listener PCB.
>
> Some things are not clear in the doxygen nor in the wiki:
> - Can I re-use a struct tcp_pcb* after I tcp_close it? I am currently
> creating a new tcp_pcb with tcp_new_ip_type every time
> - How should i gracefully close the server after the client drops the
> connection? I.e. what should I do when tcp_bind returns ERR_USE?
>
> Best regards
> K Lasocki
>
> --
> Ala ma bota



-- 
Ala ma bota

_______________________________________________
lwip-users mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/lwip-users

Reply via email to