diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h index 8c3068768f3..9647b92bca9 100644 --- a/net/tcp/tcp.h +++ b/net/tcp/tcp.h @@ -304,6 +304,7 @@ struct tcp_conn_s /* Reference to TCP close callback instance */ FAR struct devif_callback_s *clscb; + struct work_s clswork; #if defined(CONFIG_NET_TCP_WRITE_BUFFERS) /* Callback instance for TCP send() */ diff --git a/net/tcp/tcp_close.c b/net/tcp/tcp_close.c index 4a98c9833e6..86fc22a6e94 100644 --- a/net/tcp/tcp_close.c +++ b/net/tcp/tcp_close.c @@ -53,10 +53,13 @@ static void tcp_close_work(FAR void *param) net_lock(); - /* Stop the network monitor for all sockets */ + if (conn && conn->crefs == 0) + { + /* Stop the network monitor for all sockets */ - tcp_stop_monitor(conn, TCP_CLOSE); - tcp_free(conn); + tcp_stop_monitor(conn, TCP_CLOSE); + tcp_free(conn); + } net_unlock(); } @@ -175,11 +178,15 @@ static uint16_t tcp_close_eventhandler(FAR struct net_driver_s *dev, return flags; end_wait: - tcp_callback_free(conn, conn->clscb); + if (conn->clscb != NULL) + { + tcp_callback_free(conn, conn->clscb); + conn->clscb = NULL; + } /* Free network resources */ - work_queue(LPWORK, &conn->work, tcp_close_work, conn, 0); + 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 2532eb8ab1c..4c3e2990b51 100644 --- a/net/tcp/tcp_conn.c +++ b/net/tcp/tcp_conn.c @@ -769,6 +769,12 @@ void tcp_free(FAR struct tcp_conn_s *conn) DEBUGASSERT(conn->crefs == 0); + /* Cancel close work */ + + work_cancel(LPWORK, &conn->clswork); + + /* Cancel tcp timer */ + tcp_stop_timer(conn); /* Free remaining callbacks, actually there should be only the send