Fixed a number pf memory leaks in the EPICS write code

This commit is contained in:
2014-11-18 09:21:47 +01:00
parent c24049766c
commit ac5aee6062

View File

@ -5,7 +5,7 @@
* *
* copyright: see file COPYRIGHT * copyright: see file COPYRIGHT
* *
* Mark Koennecke, October 2014 * Mark Koennecke, October - November 2014
*/ */
#include <assert.h> #include <assert.h>
#include <sics.h> #include <sics.h>
@ -48,7 +48,7 @@ typedef struct {
======================================================================================*/ ======================================================================================*/
static int EpicsTask(void *userData) static int EpicsTask(void *userData)
{ {
WriteMessage mes; pWriteMessage mes;
/* /*
drive the main EPICS loop for subscriptions drive the main EPICS loop for subscriptions
@ -59,12 +59,13 @@ static int EpicsTask(void *userData)
process possible messages from the writing threads process possible messages from the writing threads
*/ */
if(epicsMessageQueueTryReceive(writeQueue,&mes,sizeof(mes)) > 0){ if(epicsMessageQueueTryReceive(writeQueue,&mes,sizeof(mes)) > 0){
if(mes.pCon == NULL){ if(mes->pCon == NULL){
traceIO("epics",mes.message); traceIO("epics",mes->message);
} else { } else {
SCWrite(mes.pCon,mes.message,eError); SCWrite(mes->pCon,mes->message,eError);
SCDeleteConnection(mes.pCon); SCDeleteConnection(mes->pCon);
} }
free(mes);
} }
return 1; return 1;
} }
@ -102,7 +103,7 @@ static int epicsConnectPV(void *message, void *userData)
SetHdbProperty(priv->node,"geterror", "Failed to connect to PV"); SetHdbProperty(priv->node,"geterror", "Failed to connect to PV");
return MPSTOP; return MPSTOP;
} }
status = ca_pend_io(3.); status = ca_pend_io(0.2);
if(status != ECA_NORMAL){ if(status != ECA_NORMAL){
SetHdbProperty(priv->node,"geterror", "Timeout connecting to PV"); SetHdbProperty(priv->node,"geterror", "Timeout connecting to PV");
return MPSTOP; return MPSTOP;
@ -273,6 +274,7 @@ static void connectPV(pHdb node, pEpicsPriv priv)
strncpy(priv->pvname,par[1]->value.v.text,sizeof(priv->pvname)); strncpy(priv->pvname,par[1]->value.v.text,sizeof(priv->pvname));
SetHdbProperty(node,"readpv", par[1]->value.v.text); SetHdbProperty(node,"readpv", par[1]->value.v.text);
AppendHipadabaCallback(node,MakeHipadabaCallback(EPICSReadCallback, priv,free)); AppendHipadabaCallback(node,MakeHipadabaCallback(EPICSReadCallback, priv,free));
connectPV(node,priv);
SCSendOK(con); SCSendOK(con);
@ -283,6 +285,7 @@ static void connectPV(pHdb node, pEpicsPriv priv)
question how to propagate error messages. The solution is a EPICS message queue to which question how to propagate error messages. The solution is a EPICS message queue to which
writing threads post. The epics task will read this queue and do the actual printing in the writing threads post. The epics task will read this queue and do the actual printing in the
SICS main thread. A convention: NULL means to print to trace. SICS main thread. A convention: NULL means to print to trace.
================================================================================================*/ ================================================================================================*/
typedef struct { typedef struct {
SConnection *pCon; SConnection *pCon;
@ -300,10 +303,13 @@ static void writeEpicsMessage(void *target, char *txt)
wm->pCon = SCCopyConnection(target); wm->pCon = SCCopyConnection(target);
} }
strncpy(wm->message,txt,sizeof(wm->message)); strncpy(wm->message,txt,sizeof(wm->message));
epicsMessageQueueSend(writeQueue,wm,sizeof(WriteMessage)); epicsMessageQueueSend(writeQueue,&wm,sizeof(pWriteMessage));
} }
} }
/*----------------------------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------------------------
To my surprise this is never called. May be, when the thread terminates anyway,
epics does not know anymore that the callback existed or how to call it.
------------------------------------------------------------------------------------------------*/
static void epicsEndCallback(struct event_handler_args args) static void epicsEndCallback(struct event_handler_args args)
{ {
char message[512]; char message[512];
@ -333,7 +339,7 @@ static void EpicsWriteFunc(void *param)
writeEpicsMessage(wp->pCon,error); writeEpicsMessage(wp->pCon,error);
goto cleanup; goto cleanup;
} }
status = ca_pend_io(5.); status = ca_pend_io(0.5);
if(status != ECA_NORMAL){ if(status != ECA_NORMAL){
snprintf(error,sizeof(error),"ERROR: failed to connect EPICS channel for %s", wp->pvName); snprintf(error,sizeof(error),"ERROR: failed to connect EPICS channel for %s", wp->pvName);
writeEpicsMessage(wp->pCon,error); writeEpicsMessage(wp->pCon,error);
@ -368,6 +374,8 @@ static void EpicsWriteFunc(void *param)
goto cleanup; goto cleanup;
} }
writeEpicsMessage(wp->pCon,"OK"); writeEpicsMessage(wp->pCon,"OK");
snprintf(error,sizeof(error),"Writing data for PV %s", wp->pvName);
writeEpicsMessage(NULL,error);
ca_pend_io(0); ca_pend_io(0);
@ -376,6 +384,8 @@ static void EpicsWriteFunc(void *param)
SCDeleteConnection(wp->pCon); SCDeleteConnection(wp->pCon);
ReleaseHdbValue(&wp->v); ReleaseHdbValue(&wp->v);
free(wp); free(wp);
ca_clear_channel(cid);
ca_context_destroy();
} }
/*----------------------------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------------------------*/
static hdbCallbackReturn EPICSWriteCallback(pHdb currentNode, static hdbCallbackReturn EPICSWriteCallback(pHdb currentNode,
@ -392,12 +402,14 @@ static hdbCallbackReturn EPICSWriteCallback(pHdb currentNode,
SCWrite(mm->callData,"ERROR: out of memory in EPICSWriteCallback", eError); SCWrite(mm->callData,"ERROR: out of memory in EPICSWriteCallback", eError);
return hdbAbort; return hdbAbort;
} }
par->pCon = SCCopyConnection(mm->callData); if(mm->callData != NULL){
par->pCon = SCCopyConnection(mm->callData);
}
cloneHdbValue(mm->v,&par->v); cloneHdbValue(mm->v,&par->v);
strncpy(par->pvName,(char *)userData,sizeof(par->pvName)); strncpy(par->pvName,(char *)userData,sizeof(par->pvName));
epicsThreadCreate("Write", epicsThreadCreate("Write",
epicsThreadPriorityHigh, epicsThreadPriorityHigh,
epicsThreadStackMedium, epicsThreadStackSmall,
EpicsWriteFunc, EpicsWriteFunc,
par); par);
} }
@ -461,7 +473,7 @@ int MakeEpicsAdapter(SConnection * con, SicsInterp * sics,
self = MakeSICSOBJv("epicsadapter", "EpicsAdapter", HIPNONE, usMugger); self = MakeSICSOBJv("epicsadapter", "EpicsAdapter", HIPNONE, usMugger);
createEPICSReadPipe(); createEPICSReadPipe();
writeQueue = epicsMessageQueueCreate(64,sizeof(WriteMessage)); writeQueue = epicsMessageQueueCreate(64,sizeof(pWriteMessage));
child = AddSICSHdbPar(self->objectNode, child = AddSICSHdbPar(self->objectNode,
"connectread", usMugger, MakeSICSFunc(EpicsConnectRead)); "connectread", usMugger, MakeSICSFunc(EpicsConnectRead));