You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/01/16 17:27:02 UTC

[incubator-nuttx] branch master updated: net/udp: break the network lock to avoid deadlock

This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 2d0baa7  net/udp: break the network lock to avoid deadlock
2d0baa7 is described below

commit 2d0baa779d997f39b8121f5965f8125184e80d71
Author: chao.an <an...@xiaomi.com>
AuthorDate: Thu Jan 16 14:20:09 2020 -0300

    net/udp: break the network lock to avoid deadlock
    
    Author: chao.an <an...@xiaomi.com>
    
        net/udp: break the network lock to avoid deadlock
    
          network deadlock when udp sendto() storm is coming
    
        net/close: force wait tx drain to complete
    
          atomic send() and close() will causes data to be discarded directly
    
    Signed-off-by: chao.an <an...@xiaomi.com>
---
 net/inet/inet_close.c               | 24 +++++++++++++-----------
 net/udp/udp_psock_sendto_buffered.c | 14 ++++++++++++++
 2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/net/inet/inet_close.c b/net/inet/inet_close.c
index 2b26a63..dd5dd83 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,21 +437,21 @@ static inline int udp_close(FAR struct socket *psock)
 
   if (_SO_GETOPT(psock->s_options, SO_LINGER))
     {
-      int ret;
+      timeout = _SO_TIMEOUT(psock->s_linger);
+    }
+#endif
 
-      /* Wait until for the buffered TX data to be sent. */
+  /* 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.
-           */
+  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);
-        }
+      nerr("ERROR: udp_txdrain() failed: %d\n", ret);
     }
-#endif
 
 #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 0dcf892..fbc44de 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)