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

xiaoxiang 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 48ecb6f922 devif:fix issue about devif_callback being released 
wrongly,resulting in no access to it
48ecb6f922 is described below

commit 48ecb6f922eb9c17185d6a54bcba10c717a75f6a
Author: wangchen <wangche...@xiaomi.com>
AuthorDate: Fri Aug 23 11:41:55 2024 +0800

    devif:fix issue about devif_callback being released wrongly,resulting in no 
access to it
    
    Signed-off-by: wangchen <wangche...@xiaomi.com>
---
 net/devif/devif.h          |  1 +
 net/devif/devif_callback.c | 92 +++++++++++++++++++++++++++++++---------------
 2 files changed, 64 insertions(+), 29 deletions(-)

diff --git a/net/devif/devif.h b/net/devif/devif.h
index 348de8636e..5b3bdaea11 100644
--- a/net/devif/devif.h
+++ b/net/devif/devif.h
@@ -274,6 +274,7 @@ struct devif_callback_s
   FAR devif_callback_event_t event;
   FAR void *priv;
   uint16_t flags;
+  uint8_t free_flags;
 };
 
 /****************************************************************************
diff --git a/net/devif/devif_callback.c b/net/devif/devif_callback.c
index af4144e431..ecd8283667 100644
--- a/net/devif/devif_callback.c
+++ b/net/devif/devif_callback.c
@@ -41,6 +41,13 @@
 #include "netdev/netdev.h"
 #include "devif/devif.h"
 
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define DEVIF_CB_DONT_FREE  (1 << 0)
+#define DEVIF_CB_PEND_FREE  (1 << 1)
+
 /****************************************************************************
  * Private Data
  ****************************************************************************/
@@ -90,35 +97,6 @@ static void devif_callback_free(FAR struct net_driver_s *dev,
         }
 #endif
 
-      /* Remove the callback structure from the device notification list if
-       * it is supposed to be in the device notification list.
-       */
-
-      if (dev != NULL)
-        {
-          /* Find the callback structure in the device event list */
-
-          for (prev = NULL, curr = dev->d_devcb;
-               curr != NULL && curr != cb;
-               prev = curr, curr = curr->nxtdev)
-            {
-            }
-
-          /* Remove the structure from the device event list */
-
-          if (curr != NULL)
-            {
-              if (prev)
-                {
-                  prev->nxtdev = cb->nxtdev;
-                }
-              else
-                {
-                  dev->d_devcb = cb->nxtdev;
-                }
-            }
-        }
-
       /* Remove the callback structure from the data notification list if
        * it is supposed to be in the data notification list.
        */
@@ -167,6 +145,48 @@ static void devif_callback_free(FAR struct net_driver_s 
*dev,
             }
         }
 
+      /* check if the callback structure has DEVIF_CB_DONT_FREE,it indicates
+       * the callback can't be free immediately,setting DEVIF_CB_PEND_FREE
+       * flag with the callback,it indicates the callback will be free
+       * finally
+       */
+
+      if (cb->free_flags & DEVIF_CB_DONT_FREE)
+        {
+          cb->free_flags |= DEVIF_CB_PEND_FREE;
+          net_unlock();
+          return;
+        }
+
+      /* Remove the callback structure from the device notification list if
+       * it is supposed to be in the device notification list.
+       */
+
+      if (dev != NULL)
+        {
+          /* Find the callback structure in the device event list */
+
+          for (prev = NULL, curr = dev->d_devcb;
+               curr != NULL && curr != cb;
+               prev = curr, curr = curr->nxtdev)
+            {
+            }
+
+          /* Remove the structure from the device event list */
+
+          if (curr != NULL)
+            {
+              if (prev)
+                {
+                  prev->nxtdev = cb->nxtdev;
+                }
+              else
+                {
+                  dev->d_devcb = cb->nxtdev;
+                }
+            }
+        }
+
       /* If this is a preallocated or a batch allocated callback store it in
        * the free callbacks list. Else free it.
        */
@@ -574,12 +594,26 @@ uint16_t devif_dev_event(FAR struct net_driver_s *dev, 
uint16_t flags)
 
       if (cb->event != NULL && devif_event_trigger(flags, cb->flags))
         {
+          cb->free_flags |= DEVIF_CB_DONT_FREE;
+
           /* Yes.. perform the callback.  Actions perform by the callback
            * may delete the current list entry or add a new list entry to
            * beginning of the list (which will be ignored on this pass)
            */
 
           flags = cb->event(dev, cb->priv, flags);
+          cb->free_flags &= ~DEVIF_CB_DONT_FREE;
+
+          /* update the next callback to prevent previously recorded the
+           * next callback from being deleted
+           */
+
+          next = cb->nxtdev;
+          if ((cb->free_flags & DEVIF_CB_PEND_FREE) != 0)
+            {
+              cb->free_flags &= ~DEVIF_CB_PEND_FREE;
+              devif_callback_free(dev, cb, NULL, NULL);
+            }
         }
     }
 

Reply via email to