- make shutdown more proper (releasing all memory)

- fixed memory leak (releaseing args when error in command)
- introduced startup commands
- modified status file writing (avoid potential corrupted files)
This commit is contained in:
zolliker
2005-09-05 08:14:33 +00:00
parent ba6cf90ab3
commit 476ad8d672
2 changed files with 94 additions and 42 deletions

109
SCinter.c
View File

@ -62,9 +62,6 @@
#include "definealias.h" #include "definealias.h"
#define MAXLEN 256
#define MAXPAR 100
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
SicsInterp *InitInterp(void) SicsInterp *InitInterp(void)
{ {
@ -91,10 +88,11 @@
return pInter; return pInter;
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
int AddCommand(SicsInterp *pInterp, char *pName, ObjectFunc pFunc, int AddCommandWithFlag(SicsInterp *pInterp, char *pName, ObjectFunc pFunc,
KillFunc pKFunc, void *pData) KillFunc pKFunc, void *pData, int startupOnly)
{ {
CommandList *pNew = NULL; CommandList *pNew = NULL;
CommandList *p, *tail;
char pBueffel[512]; char pBueffel[512];
assert(pName); assert(pName);
@ -134,19 +132,42 @@
pNew->OFunc = pFunc; pNew->OFunc = pFunc;
pNew->KFunc = pKFunc; pNew->KFunc = pKFunc;
pNew->pData = pData; pNew->pData = pData;
pNew->pNext = pInterp->pCList; pNew->pNext = NULL;
pNew->startupOnly = startupOnly;
/* find end of list */
if(pInterp->pCList) tail = NULL;
p = pInterp->pCList;
while(p != NULL)
{ {
pInterp->pCList->pPrevious = pNew; tail = p;
p = p->pNext;
} }
pNew->pPrevious = NULL; if (tail==NULL) { /* first entry */
/* update headpointer */
pInterp->pCList = pNew; pInterp->pCList = pNew;
} else { /* insert at tail */
tail->pNext = pNew;
}
pNew->pPrevious = tail;
return 1; return 1;
} }
/*------------------------------------------------------------------------*/
int AddCommand(SicsInterp *pInterp, char *pName, ObjectFunc pFunc,
KillFunc pKFunc, void *pData)
{
return AddCommandWithFlag(pInterp, pName, pFunc, pKFunc, pData, 0);
}
/*------------------------------------------------------------------------*/
int AddIniCmd(char *pName, ObjectFunc pFunc)
{
return AddCommandWithFlag(pServ->pSics, pName, pFunc, NULL, NULL, 1);
}
/*------------------------------------------------------------------------*/
int AddCmd(char *pName, ObjectFunc pFunc)
{
return AddCommandWithFlag(pServ->pSics, pName, pFunc, NULL, NULL, 0);
}
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
int RemoveCommand(SicsInterp *pInterp, char *pName) int RemoveCommand(SicsInterp *pInterp, char *pName)
{ {
@ -198,10 +219,21 @@
return 1; return 1;
} }
#define MAXLEN 256
#define MAXCOM 50 /*------------------------------------------------------------------------*/
extern char *stptok(char *s, char *tok, unsigned int toklen, char *brk); void RemoveStartupCommands(void)
extern char *SkipSpace(char *pPtr); {
CommandList *pCurrent, *pNext;
pCurrent = pServ->pSics->pCList;
while(pCurrent)
{
pNext = pCurrent->pNext;
if (pCurrent->startupOnly) {
RemoveCommand(pServ->pSics, pCurrent->pName);
}
pCurrent = pNext;
}
}
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
int InterpExecute(SicsInterp *self,SConnection *pCon, char *pText) int InterpExecute(SicsInterp *self,SConnection *pCon, char *pText)
{ {
@ -233,18 +265,21 @@ extern char *SkipSpace(char *pPtr);
/* convert to argc, argv */ /* convert to argc, argv */
argc = 0; argc = 0;
argv = NULL;
Text2Arg(pText,&argc,&argv); Text2Arg(pText,&argc,&argv);
/* the first one must be the target object. If not given an empty /* the first one must be the target object. If not given an empty
command string was given which will be silently ignored */ command string was given which will be silently ignored */
if(argc < 1) if(argc < 1)
{ {
return 1; iRet = 1;
goto deleteArgv;
} }
if(argv[0] == NULL) if(argv[0] == NULL)
{ {
SCWrite(pCon,"ERROR: failed to parse command",eError); SCWrite(pCon,"ERROR: failed to parse command",eError);
return -1; iRet = -1;
goto deleteArgv;
} }
/* find it */ /* find it */
@ -254,8 +289,8 @@ extern char *SkipSpace(char *pPtr);
sprintf(pBueffel,"ERROR: Object -> %s <- NOT found", sprintf(pBueffel,"ERROR: Object -> %s <- NOT found",
argv[0]); argv[0]);
SCWrite(pCon,pBueffel,eError); SCWrite(pCon,pBueffel,eError);
return -1; iRet = -1;
goto deleteArgv;
} }
@ -266,6 +301,8 @@ extern char *SkipSpace(char *pPtr);
iRet = pCommand->OFunc(pCon, self, pCommand->pData, argc, argv); iRet = pCommand->OFunc(pCon, self, pCommand->pData, argc, argv);
MacroPop(); MacroPop();
deleteArgv:
if (argv) {
/* delete argv */ /* delete argv */
for(i = 0; i < argc; i++) for(i = 0; i < argc; i++)
{ {
@ -275,7 +312,7 @@ extern char *SkipSpace(char *pPtr);
} }
} }
free(argv); free(argv);
}
return iRet; return iRet;
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
@ -319,23 +356,24 @@ extern char *SkipSpace(char *pPtr);
float fVal; float fVal;
pIDrivable pDriv = NULL; pIDrivable pDriv = NULL;
void *pTest = NULL; void *pTest = NULL;
char tmpfile[PATH_MAX];
int l;
assert(self); assert(self);
assert(file); assert(file);
/* open file */ /* make sure that status file is always valid M.Z. Apr 2005 */
fd = fopen(file,"w"); /* create a temporary file first */
if(!fd) l=strlen(file);
{ if (l >= sizeof tmpfile - 2) {
return 0; return 0;
} }
/* remove it, as I found garbage from previous runs in the strcpy(tmpfile, file);
status file tmpfile[l]='.';
*/ tmpfile[l+1]='\0';
fclose(fd); remove(tmpfile); /* remove already existing file */
remove(file);
fd = fopen(file,"w"); fd = fopen(tmpfile,"w");
if(!fd) if(!fd)
{ {
return 0; return 0;
@ -376,11 +414,15 @@ extern char *SkipSpace(char *pPtr);
} }
pCurrent = pCurrent->pNext; pCurrent = pCurrent->pNext;
} }
fclose(fd);
/* rename temporary to final file (this is an atomic action) */
if (0 > rename(tmpfile, file)) {
return 0;
}
if(iMot) if(iMot)
{ {
fprintf(fd,"Success \n"); fprintf(fd,"Success \n");
} }
fclose(fd);
return 1; return 1;
} }
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
@ -426,7 +468,10 @@ extern char *SkipSpace(char *pPtr);
memory problem deep in the Tcl library. This causes a core dump on memory problem deep in the Tcl library. This causes a core dump on
each SICS restart and breaks the use of external tools. each SICS restart and breaks the use of external tools.
Tcl_DeleteInterp(pTcl); Tcl_DeleteInterp(pTcl);
call KillSicsUnknown instead to clean up all memory properly. M.Z., Apr 05
*/ */
KillSicsUnknown();
} }
free(self); free(self);

View File

@ -30,6 +30,7 @@ typedef struct __Clist {
void *pData; void *pData;
struct __Clist *pNext; struct __Clist *pNext;
struct __Clist *pPrevious; struct __Clist *pPrevious;
int startupOnly;
} CommandList; } CommandList;
typedef struct __SINTER typedef struct __SINTER
@ -63,6 +64,12 @@ typedef struct __SINTER
int RemoveCommand(SicsInterp *pInterp, char *pName); int RemoveCommand(SicsInterp *pInterp, char *pName);
/* kills the command name from the interpreter pInterp /* kills the command name from the interpreter pInterp
*/ */
/*-------------------------------------------------------------------------*/
int AddCommandWithFlag(SicsInterp *pInterp, char *pName, ObjectFunc pFunc,
KillFunc pKFunc, void *pData, int startupFlag);
int AddIniCmd(char *pName, ObjectFunc pFunc); /* command will be deleted after startup */
int AddCmd(char *pName, ObjectFunc pFunc); /* syntactic sugar for AddCommand without data */
void RemoveStartupCommands(void); /* called after startup to delete startup commands */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
int InterpExecute(SicsInterp *self,pSConnection pCon,char *pCommand); int InterpExecute(SicsInterp *self,pSConnection pCon,char *pCommand);