diff --git a/net/inet/inet_close.c b/net/inet/inet_close.c index 2b26a633470..dd5dd83e974 100644 --- a/net/inet/inet_close.c +++ b/net/inet/inet_close.c @@ -412,6 +412,8 @@ static inline int tcp_close_disconnect(FAR struct socket *psock) static inline int udp_close(FAR struct socket *psock) { FAR struct udp_conn_s *conn; + unsigned int timeout = UINT_MAX; + int ret; /* Interrupts are disabled here to avoid race conditions */ @@ -435,22 +437,22 @@ static inline int udp_close(FAR struct socket *psock) if (_SO_GETOPT(psock->s_options, SO_LINGER)) { - int ret; - - /* Wait until for the buffered TX data to be sent. */ - - ret = udp_txdrain(psock, _SO_TIMEOUT(psock->s_linger)); - if (ret < 0) - { - /* udp_txdrain may fail, but that won't stop us from closing - * the socket. - */ - - nerr("ERROR: udp_txdrain() failed: %d\n", ret); - } + timeout = _SO_TIMEOUT(psock->s_linger); } #endif + /* Wait until for the buffered TX data to be sent. */ + + ret = udp_txdrain(psock, timeout); + if (ret < 0) + { + /* udp_txdrain may fail, but that won't stop us from closing + * the socket. + */ + + nerr("ERROR: udp_txdrain() failed: %d\n", ret); + } + #ifdef CONFIG_NET_UDP_WRITE_BUFFERS /* Free any semi-permanent write buffer callback in place. */ diff --git a/net/udp/udp_psock_sendto_buffered.c b/net/udp/udp_psock_sendto_buffered.c index 0dcf8927596..fbc44de0f14 100644 --- a/net/udp/udp_psock_sendto_buffered.c +++ b/net/udp/udp_psock_sendto_buffered.c @@ -75,6 +75,7 @@ #include "neighbor/neighbor.h" #include "udp/udp.h" #include "devif/devif.h" +#include "utils/utils.h" /**************************************************************************** * Pre-processor Definitions @@ -713,8 +714,21 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf, } else { + unsigned int count; + int blresult; + + /* iob_copyin might wait for buffers to be freed, but if + * network is locked this might never happen, since network + * driver is also locked, therefore we need to break the lock + */ + + blresult = net_breaklock(&count); ret = iob_copyin(wrb->wb_iob, (FAR uint8_t *)buf, len, 0, false, IOBUSER_NET_SOCK_UDP); + if (blresult >= 0) + { + net_restorelock(count); + } } if (ret < 0)