From e44e0c046eecbd3d0c88cbc79e10f8421175e476 Mon Sep 17 00:00:00 2001 From: xueyunfei Date: Wed, 4 Dec 2019 16:35:49 +0800 Subject: [PATCH] sockets: Add support for socket close from another thread 2.1.3-esp: 0a9dad95 api_msg: Support sock close from another thread 2.1.3-esp: d058bbbe sockets: Fix select-waiter when socket closed abruptly 2.1.3-esp: 46227e21 Fixes d058bbbe to unref socket for both core-lock configs 2.1.3-esp: 882716f7 sockets: Fix potential race when socket is closed already 2.1.3-esp: 8cf7089c api_msg: Fixes for sock close from another thread 2.1.3-esp: 66666948 sockets: Fix free-select-locked after udp close --- src/api/api_msg.c | 14 ++++++++++++++ src/api/sockets.c | 30 +++++++++++++++++++++++++++++- test/unit/lwipopts.h | 3 +++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/api/api_msg.c b/src/api/api_msg.c index 0fbdaa44..b5fc1a09 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -588,6 +588,9 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) tcp_err(pcb, NULL); /* remove reference from to the pcb from this netconn */ newconn->pcb.tcp = NULL; +#if ESP_LWIP && LWIP_NETCONN_FULLDUPLEX + newconn->flags |= NETCONN_FLAG_MBOXINVALID; +#endif /* ESP_LWIP && LWIP_NETCONN_FULLDUPLEX */ /* no need to drain since we know the recvmbox is empty. */ sys_mbox_free(&newconn->recvmbox); sys_mbox_set_invalid(&newconn->recvmbox); @@ -876,6 +879,9 @@ netconn_drain(struct netconn *conn) /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ /* pcb might be set to NULL already by err_tcp() */ /* drain recvmbox */ +#if ESP_LWIP + newconn->flags |= NETCONN_FLAG_MBOXINVALID; +#endif /* ESP_LWIP */ netconn_drain(newconn); if (newconn->pcb.tcp != NULL) { tcp_abort(newconn->pcb.tcp); @@ -1121,6 +1127,9 @@ lwip_netconn_do_delconn(void *m) enum netconn_state state = msg->conn->state; LWIP_ASSERT("netconn state error", /* this only happens for TCP netconns */ (state == NETCONN_NONE) || (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP)); +#if ESP_LWIP + msg->err = ERR_OK; +#endif #if LWIP_NETCONN_FULLDUPLEX /* In full duplex mode, blocking write/connect is aborted with ERR_CLSD */ if (state != NETCONN_NONE) { @@ -1133,6 +1142,9 @@ lwip_netconn_do_delconn(void *m) msg->conn->current_msg->err = ERR_CLSD; msg->conn->current_msg = NULL; msg->conn->state = NETCONN_NONE; +#if ESP_LWIP + msg->err = ERR_INPROGRESS; +#endif sys_sem_signal(op_completed_sem); } } @@ -1147,9 +1159,11 @@ lwip_netconn_do_delconn(void *m) } else #endif /* LWIP_NETCONN_FULLDUPLEX */ { +#if !ESP_LWIP LWIP_ASSERT("blocking connect in progress", (state != NETCONN_CONNECT) || IN_NONBLOCKING_CONNECT(msg->conn)); msg->err = ERR_OK; +#endif /* ESP_LWIP */ #if LWIP_NETCONN_FULLDUPLEX /* Mark mboxes invalid */ netconn_mark_mbox_invalid(msg->conn); diff --git a/src/api/sockets.c b/src/api/sockets.c index b9111943..341429de 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -482,6 +482,10 @@ tryget_socket_unconn_locked(int fd) { struct lwip_sock *ret = tryget_socket_unconn_nouse(fd); if (ret != NULL) { +#if ESP_LWIP + if (ret->conn == NULL) + return NULL; +#endif /* ESP_LWIP */ if (!sock_inc_used_locked(ret)) { return NULL; } @@ -600,6 +604,9 @@ free_socket_locked(struct lwip_sock *sock, int is_tcp, struct netconn **conn, *lastdata = sock->lastdata; sock->lastdata.pbuf = NULL; +#if ESP_LWIP + sock->select_waiting = 0; +#endif /* ESP_LWIP */ *conn = sock->conn; sock->conn = NULL; return 1; @@ -2621,6 +2628,9 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) static void select_check_waiters(int s, int has_recvevent, int has_sendevent, int has_errevent) { struct lwip_select_cb *scb; +#if ESP_LWIP + struct lwip_sock *sock; +#endif /* ESP_LWIP */ #if !LWIP_TCPIP_CORE_LOCKING int last_select_cb_ctr; SYS_ARCH_DECL_PROTECT(lev); @@ -2628,6 +2638,9 @@ static void select_check_waiters(int s, int has_recvevent, int has_sendevent, in LWIP_ASSERT_CORE_LOCKED(); +#if ESP_LWIP + sock = tryget_socket_unconn(s); +#endif /* ESP_LWIP */ #if !LWIP_TCPIP_CORE_LOCKING SYS_ARCH_PROTECT(lev); again: @@ -2649,17 +2662,29 @@ again: #if LWIP_SOCKET_SELECT { /* Test this select call for our socket */ +#if ESP_LWIP + if (sock->rcvevent) { +#else if (has_recvevent) { +#endif /* ESP_LWIP */ if (scb->readset && FD_ISSET(s, scb->readset)) { do_signal = 1; } } +#if ESP_LWIP + if (sock->sendevent) { +#else if (has_sendevent) { +#endif /* ESP_LWIP */ if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) { do_signal = 1; } } +#if ESP_LWIP + if (sock->errevent) { +#else if (has_errevent) { +#endif /* ESP_LWIP */ if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) { do_signal = 1; } @@ -2689,7 +2714,10 @@ again: last_select_cb_ctr = select_cb_ctr; } SYS_ARCH_UNPROTECT(lev); -#endif +#endif /* LWIP_TCPIP_CORE_LOCKING */ +#if ESP_LWIP + done_socket(sock); +#endif /* ESP_LWIP */ } #endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */ diff --git a/test/unit/lwipopts.h b/test/unit/lwipopts.h index 0ee09dff..37bcd874 100644 --- a/test/unit/lwipopts.h +++ b/test/unit/lwipopts.h @@ -91,4 +91,7 @@ /* Check lwip_stats.mem.illegal instead of asserting */ #define LWIP_MEM_ILLEGAL_FREE(msg) /* to nothing */ +/* Enable Espressif specific options */ +#define ESP_LWIP 1 + #endif /* LWIP_HDR_LWIPOPTS_H */