]> granicus.if.org Git - esp-idf/commitdiff
lwip: fix tcp_pcb_purge assert
authorLiu Zhi Fu <liuzhifu@espressif.com>
Fri, 27 Apr 2018 06:05:55 +0000 (14:05 +0800)
committerLiu Zhi Fu <liuzhifu@espressif.com>
Wed, 6 Jun 2018 02:25:01 +0000 (10:25 +0800)
Remove the assert in tcp_pcb_purge()

components/lwip/core/tcp.c

index 920523e45d603f6015821412734aad8aba52fd23..35649f12fa55fc015211ad680238deaf54875486 100644 (file)
@@ -1751,19 +1751,31 @@ tcp_pcb_purge(struct tcp_pcb *pcb)
     if (pcb->state == SYN_RCVD) {
       /* Need to find the corresponding listen_pcb and decrease its accepts_pending */
       struct tcp_pcb_listen *lpcb;
-      LWIP_ASSERT("tcp_pcb_purge: pcb->state == SYN_RCVD but tcp_listen_pcbs is NULL",
-        tcp_listen_pcbs.listen_pcbs != NULL);
-      for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
-        if ((lpcb->local_port == pcb->local_port) &&
-            (IP_IS_V6_VAL(pcb->local_ip) == IP_IS_V6_VAL(lpcb->local_ip)) &&
-            (ip_addr_isany(&lpcb->local_ip) ||
-             ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) {
-            /* port and address of the listen pcb match the timed-out pcb */
-            LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending",
-              lpcb->accepts_pending > 0);
-            lpcb->accepts_pending--;
-            break;
+
+      /*
+       * The official LWIP will assert the system if tcp_listen_pcbs.listen_pcbs is NULL, it's a bug.
+       *
+       * Considering following scenario:
+       * 1. On TCP server side, one of TCP pcb is in SYNC_RECV state and is waiting for TCP ACK from TCP client.
+       * 2. The TCP server is closed by application, which causes the tcp_listen_pcbs.listen_pcbs to become NULL.
+       * 3. When SYNC_RECV state timeout (20s by default), tcp_pcb_purge() is called in tcp_slowtmr(), it asserts
+       *    the system.
+       * This is a normal scenario, should NOT assert the system. So just remove it.
+       * 
+       */
+      if (tcp_listen_pcbs.listen_pcbs) {
+        for (lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) {
+          if ((lpcb->local_port == pcb->local_port) &&
+              (IP_IS_V6_VAL(pcb->local_ip) == IP_IS_V6_VAL(lpcb->local_ip)) &&
+              (ip_addr_isany(&lpcb->local_ip) ||
+               ip_addr_cmp(&pcb->local_ip, &lpcb->local_ip))) {
+              /* port and address of the listen pcb match the timed-out pcb */
+              LWIP_ASSERT("tcp_pcb_purge: listen pcb does not have accepts pending",
+                lpcb->accepts_pending > 0);
+              lpcb->accepts_pending--;
+              break;
           }
+        }
       }
     }
 #endif /* TCP_LISTEN_BACKLOG */