diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h index 255dbe4c964..eb989e5fa9e 100644 --- a/net/tcp/tcp.h +++ b/net/tcp/tcp.h @@ -106,12 +106,13 @@ #define TCP_WSCALE 0x01U /* Window Scale option enabled */ #define TCP_SACK 0x02U /* Selective ACKs enabled */ +#define TCP_CLOSE_ARRANGED 0x04U /* Connection is arranged to be freed */ #ifdef CONFIG_NET_TCP_CC_NEWRENO /* The TCP flags for congestion control */ -#define TCP_INFR 0x04U /* The flag in Fast Recovery */ -#define TCP_INFT 0x08U /* The flag in Fast Transmitted */ +#define TCP_INFR 0x08U /* The flag in Fast Recovery */ +#define TCP_INFT 0x10U /* The flag in Fast Transmitted */ #endif diff --git a/net/tcp/tcp_close.c b/net/tcp/tcp_close.c index 3892d898c77..bc1e424bd74 100644 --- a/net/tcp/tcp_close.c +++ b/net/tcp/tcp_close.c @@ -53,7 +53,8 @@ static void tcp_close_work(FAR void *param) net_lock(); - if (conn && conn->crefs == 0) + conn->flags &= ~TCP_CLOSE_ARRANGED; + if (conn->crefs == 0) { /* Stop the network monitor for all sockets */ @@ -186,6 +187,7 @@ end_wait: /* Free network resources */ + conn->flags |= TCP_CLOSE_ARRANGED; work_queue(LPWORK, &conn->clswork, tcp_close_work, conn, 0); return flags; diff --git a/net/tcp/tcp_conn.c b/net/tcp/tcp_conn.c index b421d9d4536..d786646707a 100644 --- a/net/tcp/tcp_conn.c +++ b/net/tcp/tcp_conn.c @@ -842,7 +842,14 @@ void tcp_free(FAR struct tcp_conn_s *conn) /* Cancel close work */ - work_cancel(LPWORK, &conn->clswork); + if ((conn->flags & TCP_CLOSE_ARRANGED) && + work_cancel(LPWORK, &conn->clswork) != OK) + { + /* Close work is already running, tcp_free will be called again. */ + + net_unlock(); + return; + } /* Cancel tcp timer */