I wrote this little routine to allow me to load database records into the IOC upon startup.
// Set this to use 'tmpfile' to create a temprary file, or don't set to use tempname and create an actual file in /tmp
//#define USE_TMPFILE
void loadMyDatabaseRecords(void)
{
char *pptr = NULL;
char *subsPtr = NULL;
FILE *tempFile = NULL;
const char substring[] = "P=";
#ifndef USE_TMPFILE
char nameTemplate[] = "BNET";
char *tempName;
#endif
/* Generate a temporary file, and write the database definition of the diagnostics record into it. */
#ifdef USE_TMPFILE
tempFile = tmpfile();
#else
tempName = tempnam(NULL, nameTemplate);
printf("Opening %s\n",tempName);
tempFile=fopen(tempName, "w+");
#endif
if(tempFile) {
size_t i;
i=fputs(recordsDef, tempFile);
#ifdef USE_TMPFILE
// rewind the file to the start
rewind(tempFile);
#else
// If I'm using a file to do this, lets just close the file at the moment.
fclose(tempFile);
#endif
// Not quite ready yet, I need to fill out my "substitutions" buffer
pptr=getenv("IOCNAME");
i=strlen(substring)+strlen(pptr);
subsPtr = (char *) calloc(sizeof(char), i+1);
strncpy(subsPtr, substring, strlen(substring) );
strncat(subsPtr, pptr, strlen(pptr)+1);
#ifdef USE_TMPFILE
printf("Loading new database\n");
// use dbReadDatabaseFP to load the file
dbReadDatabaseFP(&pdbbase, tempFile, NULL, subsPtr);
#else
printf("Loading my temp file %s\n",tempName);
// use dbReadDatabase to load the file
dbReadDatabase(&pdbbase, tempName, NULL, subsPtr);
free(tempName);
#endif
printf("Done\n");
free(subsPtr);
printf("Closing file\n");
#ifdef USE_TMPFILE
// Closing the file will delete it as well.
fclose(tempFile);
#else
#endif
}
}
This is triggered during the iocInit startup during the initHookAtIocBuild state, and I’ve also tried it at the initHookAtBeginning state as well.
So, if I have ‘USE_TMPFILE’ defined, the routine uses ‘tmpfile’ and creates a temporary file, writes the database info to it, and then calls ‘dbReadDatabaseFP’. If it’s not defined, the routine generates a temporary file, writes the database
info into it, closes the file and uses ‘dbReadDatabase’ to load it. There’s more maintenance needed in doing things with ‘dbReadDatabase’, but what the heck-
Now, here’s the rub…..
If I don’t define ‘USE_TMPFILE’, the routine generates a proper temporary file, writes a proper record to it, closes the file, etc… and calls ‘dbReadDatabase’ and works great.
If I do define ‘USE_TMPFILE’ (which was my original idea), it creates the temporary file, writes a proper record to it (I have checked this), and then calls ‘dbReadDatabaseFP’.
In this case, the IOC shows that it loaded the database, closed the file, and then I get a ‘free(): double free detected in tcache 2’ error and the IOC aborts.
This is with the latest version of EPICS 7 (just ‘git pull’d this morning, on Debian Bulldog.
Note that I’ve figured a way around this error, but want to report it just the same, in case this is a possible bug.
Later-
David Dudley
Controls Engineer III
Facility for Rare Isotope Beams
Michigan State University
640 South Shaw Lane
East Lansing, MI 48824-1321, USA
Tel. 517-908-7133
Email: dudleyd@frib.msu.edu
|
|