asTrap serverSpecific is dbChannel

Save/restore dbAddr::pfield around callbacks to
avoid corruption if CB forgets to restore.

Need to peak at dbChannel.h during libCom build.
So generate dbCoreAPI.h early, and add extra
-I to source location when compiling dbTrapWrite.c
This commit is contained in:
Michael Davidsaver
2024-06-11 15:17:14 -07:00
committed by Andrew Johnson
parent e6a2047bbf
commit f6cd43b7cc
6 changed files with 24 additions and 6 deletions

View File

@ -16,7 +16,7 @@ USR_CPPFLAGS += -DUSE_TYPED_RSET -DUSE_TYPED_DSET
# Shared library ABI version. # Shared library ABI version.
SHRLIB_VERSION = $(EPICS_DATABASE_MAJOR_VERSION).$(EPICS_DATABASE_MINOR_VERSION).$(EPICS_DATABASE_MAINTENANCE_VERSION) SHRLIB_VERSION = $(EPICS_DATABASE_MAJOR_VERSION).$(EPICS_DATABASE_MINOR_VERSION).$(EPICS_DATABASE_MAINTENANCE_VERSION)
API_HEADER = dbCoreAPI.h # dbCoreAPI.h generated earlier during libcom/
dbCore_API = dbCore dbCore_API = dbCore
LIBRARY_IOC += dbCore LIBRARY_IOC += dbCore

View File

@ -54,6 +54,8 @@ include $(LIBCOM)/yajl/Makefile
# Generate library API header file # Generate library API header file
API_HEADER = libComAPI.h API_HEADER = libComAPI.h
Com_API = libCom Com_API = libCom
# Generate early to allow a sneak peak at dbChannel.h
API_HEADER += dbCoreAPI.h
# Library to build: # Library to build:
LIBRARY=Com LIBRARY=Com

View File

@ -19,4 +19,8 @@ INC += asTrapWrite.h
Com_SRCS += asLib.c Com_SRCS += asLib.c
Com_SRCS += asTrapWrite.c Com_SRCS += asTrapWrite.c
# Allow early access to dbChannel.h
asTrapWrite_CPPFLAGS = -I$(LIBCOM)/../../database/src/ioc/db
CLEANS += asLib.c asLib_lex.c CLEANS += asLib.c asLib_lex.c

View File

@ -22,6 +22,8 @@
extern "C" { extern "C" {
#endif #endif
struct dbChannel;
/* 0 - Use (unverified) client provided host name string. /* 0 - Use (unverified) client provided host name string.
* 1 - Use actual client IP address. HAG() are resolved to IPs at ACF load time. * 1 - Use actual client IP address. HAG() are resolved to IPs at ACF load time.
*/ */
@ -121,7 +123,7 @@ LIBCOM_API int epicsStdCall asDumpHash(void);
LIBCOM_API int epicsStdCall asDumpHashFP(FILE *fp); LIBCOM_API int epicsStdCall asDumpHashFP(FILE *fp);
LIBCOM_API void * epicsStdCall asTrapWriteBeforeWithData( LIBCOM_API void * epicsStdCall asTrapWriteBeforeWithData(
const char *userid, const char *hostid, void *addr, const char *userid, const char *hostid, struct dbChannel *addr,
int dbrType, int no_elements, void *data); int dbrType, int no_elements, void *data);
LIBCOM_API void epicsStdCall asTrapWriteAfterWrite(void *pvt); LIBCOM_API void epicsStdCall asTrapWriteAfterWrite(void *pvt);

View File

@ -22,10 +22,10 @@
#include "ellLib.h" #include "ellLib.h"
#include "freeList.h" #include "freeList.h"
#include "epicsStdio.h"
#include "cantProceed.h" #include "cantProceed.h"
#include "epicsMutex.h" #include "epicsMutex.h"
#include "ellLib.h" #include "ellLib.h"
#include <dbChannel.h>
#include "asLib.h" #include "asLib.h"
#include "asTrapWrite.h" #include "asTrapWrite.h"
@ -112,11 +112,12 @@ void epicsStdCall asTrapWriteUnregisterListener(asTrapWriteId id)
} }
void * epicsStdCall asTrapWriteBeforeWithData( void * epicsStdCall asTrapWriteBeforeWithData(
const char *userid, const char *hostid, void *addr, const char *userid, const char *hostid, dbChannel *chan,
int dbrType, int no_elements, void *data) int dbrType, int no_elements, void *data)
{ {
writeMessage *pwriteMessage; writeMessage *pwriteMessage;
listener *plistener; listener *plistener;
void *pfieldsave;
if (pasTrapWritePvt == 0 || if (pasTrapWritePvt == 0 ||
ellCount(&pasTrapWritePvt->listenerList) <= 0) return 0; ellCount(&pasTrapWritePvt->listenerList) <= 0) return 0;
@ -125,13 +126,14 @@ void * epicsStdCall asTrapWriteBeforeWithData(
pasTrapWritePvt->freeListWriteMessage); pasTrapWritePvt->freeListWriteMessage);
pwriteMessage->message.userid = userid; pwriteMessage->message.userid = userid;
pwriteMessage->message.hostid = hostid; pwriteMessage->message.hostid = hostid;
pwriteMessage->message.serverSpecific = addr; pwriteMessage->message.serverSpecific = chan;
pwriteMessage->message.dbrType = dbrType; pwriteMessage->message.dbrType = dbrType;
pwriteMessage->message.no_elements = no_elements; pwriteMessage->message.no_elements = no_elements;
pwriteMessage->message.data = data; pwriteMessage->message.data = data;
ellInit(&pwriteMessage->listenerPvtList); ellInit(&pwriteMessage->listenerPvtList);
epicsMutexMustLock(pasTrapWritePvt->lock); epicsMutexMustLock(pasTrapWritePvt->lock);
pfieldsave = chan->addr.pfield;
ellAdd(&pasTrapWritePvt->writeMessageList, &pwriteMessage->node); ellAdd(&pasTrapWritePvt->writeMessageList, &pwriteMessage->node);
plistener = (listener *)ellFirst(&pasTrapWritePvt->listenerList); plistener = (listener *)ellFirst(&pasTrapWritePvt->listenerList);
while (plistener) { while (plistener) {
@ -141,6 +143,7 @@ void * epicsStdCall asTrapWriteBeforeWithData(
plistenerPvt->plistener = plistener; plistenerPvt->plistener = plistener;
pwriteMessage->message.userPvt = 0; pwriteMessage->message.userPvt = 0;
plistener->func(&pwriteMessage->message, 0); plistener->func(&pwriteMessage->message, 0);
chan->addr.pfield = pfieldsave;
plistenerPvt->userPvt = pwriteMessage->message.userPvt; plistenerPvt->userPvt = pwriteMessage->message.userPvt;
ellAdd(&pwriteMessage->listenerPvtList, &plistenerPvt->node); ellAdd(&pwriteMessage->listenerPvtList, &plistenerPvt->node);
plistener = (listener *)ellNext(&plistener->node); plistener = (listener *)ellNext(&plistener->node);
@ -153,11 +156,15 @@ void epicsStdCall asTrapWriteAfterWrite(void *pvt)
{ {
writeMessage *pwriteMessage = (writeMessage *)pvt; writeMessage *pwriteMessage = (writeMessage *)pvt;
listenerPvt *plistenerPvt; listenerPvt *plistenerPvt;
dbChannel *chan;
void *pfieldsave;
if (pwriteMessage == 0 || if (pwriteMessage == 0 ||
pasTrapWritePvt == 0) return; pasTrapWritePvt == 0) return;
epicsMutexMustLock(pasTrapWritePvt->lock); epicsMutexMustLock(pasTrapWritePvt->lock);
chan = pwriteMessage->message.serverSpecific;
pfieldsave = chan->addr.pfield;
plistenerPvt = (listenerPvt *)ellFirst(&pwriteMessage->listenerPvtList); plistenerPvt = (listenerPvt *)ellFirst(&pwriteMessage->listenerPvtList);
while (plistenerPvt) { while (plistenerPvt) {
listenerPvt *pnext = (listenerPvt *)ellNext(&plistenerPvt->node); listenerPvt *pnext = (listenerPvt *)ellNext(&plistenerPvt->node);
@ -165,6 +172,7 @@ void epicsStdCall asTrapWriteAfterWrite(void *pvt)
pwriteMessage->message.userPvt = plistenerPvt->userPvt; pwriteMessage->message.userPvt = plistenerPvt->userPvt;
plistener->func(&pwriteMessage->message, 1); plistener->func(&pwriteMessage->message, 1);
chan->addr.pfield = pfieldsave;
ellDelete(&pwriteMessage->listenerPvtList, &plistenerPvt->node); ellDelete(&pwriteMessage->listenerPvtList, &plistenerPvt->node);
freeListFree(pasTrapWritePvt->freeListListenerPvt, plistenerPvt); freeListFree(pasTrapWritePvt->freeListListenerPvt, plistenerPvt);
plistenerPvt = pnext; plistenerPvt = pnext;

View File

@ -26,6 +26,8 @@
extern "C" { extern "C" {
#endif #endif
struct dbChannel;
/** /**
* \brief The message passed to registered listeners. * \brief The message passed to registered listeners.
*/ */
@ -39,7 +41,7 @@ typedef struct asTrapWriteMessage {
* the value the server provides to asTrapWriteWithData(), which * the value the server provides to asTrapWriteWithData(), which
* for RSRV is the dbChannel pointer for the target field. * for RSRV is the dbChannel pointer for the target field.
*/ */
void *serverSpecific; struct dbChannel *serverSpecific;
/** \brief A field for use by the \ref asTrapWriteListener. /** \brief A field for use by the \ref asTrapWriteListener.
* *
* When the listener is called before the write, this has the * When the listener is called before the write, this has the