From 49fddaa13e10b3c524fa1d294f6d31392aa288af Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Tue, 15 Nov 2022 07:59:22 -0800 Subject: [PATCH] errlogRemoveListeners() handle self-removal Handle errlogRemoveListeners() during a callback. --- modules/libcom/src/error/errlog.c | 27 +++++++++++++++++++++++---- modules/libcom/src/error/errlog.h | 3 +++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/modules/libcom/src/error/errlog.c b/modules/libcom/src/error/errlog.c index 79361e42a..6ae267323 100644 --- a/modules/libcom/src/error/errlog.c +++ b/modules/libcom/src/error/errlog.c @@ -66,6 +66,8 @@ typedef struct listenerNode{ ELLNODE node; errlogListener listener; void *pPrivate; + unsigned active:1; + unsigned removed:1; } listenerNode; typedef struct { @@ -442,9 +444,15 @@ int errlogRemoveListeners(errlogListener listener, void *pPrivate) listenerNode *pnext = (listenerNode *)ellNext(&plistenerNode->node); if (plistenerNode->listener == listener && - plistenerNode->pPrivate == pPrivate) { - ellDelete(&pvt.listenerList, &plistenerNode->node); - free(plistenerNode); + plistenerNode->pPrivate == pPrivate) + { + if(plistenerNode->active) { /* callback removing itself */ + plistenerNode->removed = 1; + + } else { + ellDelete(&pvt.listenerList, &plistenerNode->node); + free(plistenerNode); + } ++count; } plistenerNode = pnext; @@ -674,8 +682,19 @@ static void errlogThread(void) epicsMutexMustLock(pvt.listenerLock); plistenerNode = (listenerNode *)ellFirst(&pvt.listenerList); while (plistenerNode) { + listenerNode *next; + + plistenerNode->active = 1; (*plistenerNode->listener)(plistenerNode->pPrivate, base+1u); - plistenerNode = (listenerNode *)ellNext(&plistenerNode->node); + plistenerNode->active = 0; + + next = (listenerNode *)ellNext(&plistenerNode->node); + if(plistenerNode->removed) { + /* listener() called errlogRemoveListeners() */ + ellDelete(&pvt.listenerList, &plistenerNode->node); + free(plistenerNode); + } + plistenerNode = next; } epicsMutexUnlock(pvt.listenerLock); diff --git a/modules/libcom/src/error/errlog.h b/modules/libcom/src/error/errlog.h index 133fe8be7..7cec39653 100644 --- a/modules/libcom/src/error/errlog.h +++ b/modules/libcom/src/error/errlog.h @@ -178,6 +178,9 @@ LIBCOM_API void errlogAddListener(errlogListener listener, void *pPrivate); * * \param listener Function pointer of type ::errlogListener * \param pPrivate This will be passed as the first argument of listener() + * + * \since UNRELEASED Safe to call from a listener callback. + * \until UNRELEASED Self-removal from a listener callback caused corruption. */ LIBCOM_API int errlogRemoveListeners(errlogListener listener, void *pPrivate);