1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 <2022> 2023 2024 2025 | Index | 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 <2022> 2023 2024 2025 |
<== Date ==> | <== Thread ==> |
---|
Subject: | Possible bug??? in dbReadDatabaseFP |
From: | "Dudley, David via Tech-talk" <tech-talk at aps.anl.gov> |
To: | "tech-talk at aps.anl.gov" <tech-talk at aps.anl.gov> |
Date: | Thu, 3 Mar 2022 16:16:47 +0000 |
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-
|
// 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 } }