EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

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  <20222023  2024  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  <20222023  2024 
<== 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-

 

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

 

 

cid:image002.jpg@01D07041.57B6D750

 

 

// 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
	}
}


Replies:
Re: Possible bug??? in dbReadDatabaseFP Michael Davidsaver via Tech-talk

Navigate by Date:
Prev: Re: RHEL8 as an NFS server for RTEMS Joel Sherrill via Tech-talk
Next: Re: Timing in seq record Andrew Johnson via Tech-talk
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  <20222023  2024 
Navigate by Thread:
Prev: Re: RHEL8 as an NFS server for RTEMS Joel Sherrill via Tech-talk
Next: Re: Possible bug??? in dbReadDatabaseFP Michael Davidsaver via Tech-talk
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  <20222023  2024 
ANJ, 14 Sep 2022 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·