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

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


The following commit(s) were added to refs/heads/master by this push:
     new 0f1a49bba5 tun: Fix the error of calling tun_close when tun_txavail or 
tun_txavail_work is executed
0f1a49bba5 is described below

commit 0f1a49bba57691946e30f7bf4847b5788b5d41f9
Author: zhanghongyu <zhanghon...@xiaomi.com>
AuthorDate: Fri Oct 20 15:17:48 2023 +0800

    tun: Fix the error of calling tun_close when tun_txavail or 
tun_txavail_work is executed
    
    When tun_txavail_work is running, switch to tun_close thread and priv->lock 
will be destroyed, then switch back to tun_txavail_work thread, an error will 
occur when nxmutex_unlock(&priv->lock)
    
    Signed-off-by: zhanghongyu <zhanghon...@xiaomi.com>
---
 drivers/net/tun.c | 38 +++++++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 3f00b0b365..e40017adf6 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -184,7 +184,7 @@ static int tun_rmmac(FAR struct net_driver_s *dev, FAR 
const uint8_t *mac);
 static int tun_dev_init(FAR struct tun_device_s *priv,
                         FAR struct file *filep,
                         FAR const char *devfmt, bool tun);
-static void tun_dev_uninit(FAR struct tun_device_s *priv);
+static int tun_dev_uninit(FAR struct tun_device_s *priv);
 
 /* File interface */
 
@@ -775,14 +775,22 @@ static void tun_txavail_work(FAR void *arg)
 static int tun_txavail(FAR struct net_driver_s *dev)
 {
   FAR struct tun_device_s *priv = (FAR struct tun_device_s *)dev->d_private;
+  int ret = nxmutex_lock(&priv->lock);
+
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Schedule to perform the TX poll on the worker thread. */
 
-  if (work_available(&priv->work))
+  if (priv->bifup && work_available(&priv->work))
     {
       work_queue(TUNWORK, &priv->work, tun_txavail_work, priv, 0);
     }
 
+  nxmutex_unlock(&priv->lock);
+
   return OK;
 }
 
@@ -905,12 +913,27 @@ static int tun_dev_init(FAR struct tun_device_s *priv,
  * Name: tun_dev_uninit
  ****************************************************************************/
 
-static void tun_dev_uninit(FAR struct tun_device_s *priv)
+static int tun_dev_uninit(FAR struct tun_device_s *priv)
 {
+  int ret;
+
+  ret = nxmutex_lock(&priv->lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
   /* Put the interface in the down state */
 
   tun_ifdown(&priv->dev);
 
+  if (!work_available(&priv->work))
+    {
+      work_cancel_sync(TUNWORK, &priv->work);
+    }
+
+  nxmutex_unlock(&priv->lock);
+
   /* Remove the device from the OS */
 
   netdev_unregister(&priv->dev);
@@ -918,6 +941,8 @@ static void tun_dev_uninit(FAR struct tun_device_s *priv)
   nxmutex_destroy(&priv->lock);
   nxsem_destroy(&priv->read_wait_sem);
   nxsem_destroy(&priv->write_wait_sem);
+
+  return ret;
 }
 
 /****************************************************************************
@@ -941,8 +966,11 @@ static int tun_close(FAR struct file *filep)
   ret  = nxmutex_lock(&tun->lock);
   if (ret >= 0)
     {
-      tun->free_tuns |= (1 << intf);
-      tun_dev_uninit(priv);
+      ret = tun_dev_uninit(priv);
+      if (ret >= 0)
+        {
+          tun->free_tuns |= (1 << intf);
+        }
 
       nxmutex_unlock(&tun->lock);
     }

Reply via email to