Skip to content

Commit

Permalink
devif:fix issue about devif_callback being released wrongly,resulting…
Browse files Browse the repository at this point in the history
… in no access to it

Signed-off-by: wangchen <[email protected]>
  • Loading branch information
wangchen61698 committed Aug 23, 2024
1 parent 4d4d8a6 commit 4752191
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 29 deletions.
1 change: 1 addition & 0 deletions net/devif/devif.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ struct devif_callback_s
FAR devif_callback_event_t event;
FAR void *priv;
uint16_t flags;
uint8_t free_flags;
};

/****************************************************************************
Expand Down
92 changes: 63 additions & 29 deletions net/devif/devif_callback.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,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
****************************************************************************/
Expand Down Expand Up @@ -88,35 +95,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.
*/
Expand Down Expand Up @@ -165,6 +143,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.
*/
Expand Down Expand Up @@ -572,12 +592,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);
}
}
}

Expand Down

0 comments on commit 4752191

Please sign in to comment.