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  <20152016  2017  2018  2019  2020  2021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  <20152016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: RE: Problems using static database routines to modify IOCs
From: <[email protected]>
To: <[email protected]>
Cc: [email protected]
Date: Thu, 7 May 2015 23:51:27 +0000
Hi Doug,

There is a good tool called dependency walker http://www.dependencywalker.com/ that will show exactly which DLLs  are referenced by other DLLs/executables - might be worth running this and checking everything is as you think it should be. You can get strange crashes in programs that load multiple versions of the MSVC library - it's not automatically a problem, but if resources are allocated in a DLL using one library version and then passed to and freed in a DLL using another library version then that can lead to a crash. 

Regards,

Freddie

> -----Original Message-----
> From: [email protected] [mailto:[email protected]]
> Sent: 07 May 2015 19:56
> To: Akeroyd, Freddie (STFC,RAL,ISIS)
> Cc: [email protected]; [email protected]
> Subject: RE: Problems using static database routines to modify IOCs
> 
> Hi Freddie,
> 
> Thank you for spending time looking at this for me. Unfortunately, I'm
> still having the issue. I get access violations from several dlls not just
> dbStaticHost.dll and they all involve a string function call. I checked
> into what you found out and I believe I'm only building against the IOC
> libraries but the code is built as a MS Visual Studio project which I have
> almost no experience with, so I'm not certain.
> 
> Here's what I have learned over the week.
> 
> I decided to try to add the database dump code to the example IOC
> application that comes with EPICS.
> 
> First I booted my Scientific Linux partition and built the example IOC
> with gcc. After I tested the IOC I added the dump code to the IOC Main and
> recompiled. The modified code worked perfectly.
> 
> Next, I booted Windows 8 and built EPICS with the MS Visual Studio 2012
> compiler. I then built the example IOC and ran it successfully. I added
> the dump routine to Main and recompiled and again the IOC ran flawlessly.
> 
> Finally, I went to the test computer I've been working on, Windows 7 32
> bit. EPICS was built on it using MS VS 2012. I built the example IOC again
> and it ran with no issues. I added the dump routine and recompiled and it
> ran with no problems!
> 
> So it appears that the problem I'm having is in one of two things or maybe
> both. Either there is a problem in the already modified IOC code that I'm
> trying to add this dump routine to, or there is a problem with the way the
> IOC is built. In all my successes I used the make files, but the IOC I'm
> working on is saved as a MS VS project.
> 
> So at this point I'm trying to build the example IOC as a MS VS project,
> so that I can learn about Visual Studio. Once that works I'll look at the
> IOC code that was added before I worked on this. I know one routine that
> was added converts TwinCAT PLC files into db files which are then used by
> the IOC. So maybe there is something in that routine that causes an error
> in the global pdbbase at initialization.
> 
> It's strange though because pdbbase works fine within the IOC once the
> shell is running, I can use all of the built in db routines with no
> issues. It's only during initialization that this error occurs.
> 
> In any case at least I feel like I have direction rather than blankly
> staring at code that 'should' work!
> 
> Thank you all again for your time, suggestions, and guidance,
> Doug Lormand
> 
> 
> > Hi Doug,
> >
> > I've managed to reproduce your problem - it was a bit confusing at first
> > as your example worked fine for me, but then I recalled that in your
> > original message the crash was in dbStaticHost.dll rather than
> > dbStaticIoc.dll
> >
> >     "Unhandled exception at 0x5C6F1C6E (dbStaticHost.dll) in tcIoc.exe:
> > 0xC0000005: Access violation reading location 0x00000031."
> >
> > Running a dependency walker on my test IOC showed neither a direct nor
> > indirect reference to this DLL. I changed my IOC Makefile LIBS  line from:
> >
> >     $(APPNAME)_LIBS += $(EPICS_BASE_IOC_LIBS)
> >
> > to:
> >
> >     $(APPNAME)_LIBS += $(EPICS_BASE_HOST_LIBS)
> $(EPICS_BASE_IOC_LIBS)
> >
> > and then I had a crash at dbGetString() in dbStaticHost.dll   So I'm
> > guessing you are linking against both HOST and IOC libraries and you just
> > need to remove references to the HOST libraries from your Makefile for it
> > to work
> >
> > Regards,
> >
> > Freddie
> >
> >> -----Original Message-----
> >> From: [email protected] [mailto:tech-talk-
> >> [email protected]] On Behalf Of [email protected]
> >> Sent: 01 May 2015 23:59
> >> To: Andrew Johnson
> >> Cc: [email protected]; EPICS
> >> Subject: Re: Problems using static database routines to modify IOCs
> >>
> >> Hello Andrew and Tim,
> >>
> >> Ok here's what I am attempting to do.
> >>
> >> The goal is at IOC startup after initialization to be able to compare a
> >> set of channel values with a saved set of values, so that any
> >> differences
> >> can be investigated.
> >>
> >> The IOC I am tying to modify is running on a Windows 7 computer and I'm
> >> using Visual Studio 2012 update 4.
> >>
> >> The first step in this was to modify the Windows IOC so that it would
> >> perform a database dump to standard output right before the ioc shell is
> >> invoked. This was really just to get some experience modifying and
> >> working
> >> with IOC code.
> >>
> >> So I took the iocMain.cpp and literally copied the dbDumpRecords
> example
> >> function at the end of the EPICS application developer's guide, chapter
> >> 14.16.2. After adding that function prototype and the function to the
> >> iocMain.cpp, I am trying to call the function in main() right before the
> >> iocsh(NULL) call.
> >>
> >> Everything compiles ok but I am clearly not pointing to the right place
> >> since I get garbage plus the IOC crashes. The only way it works was to
> >> load a second instance of the database into memory which you are right
> >> is
> >> not what I want to do.
> >>
> >> Here is the iocMain.cpp code,
> >>
> >>
> >>
> >> #include "epicsExit.h"
> >> #include "epicsThread.h"
> >> #include "iocsh.h"
> >> #include <ctime>
> >> #include "dbAccess.h"
> >> #include "dbStaticLib.h"
> >> #include "dbDefs.h"
> >> #include "dbFldTypes.h"
> >> #include "link.h"
> >>
> >> extern "C" {
> >> __declspec(dllimport) void stopPLCs(void);
> >> }
> >>
> >> // Function proto types
> >> ************************************************
> >>
> >> void dbDumpRecords(DBBASE *);					//
> >> code I added <---------------------
> >>
> >> // Function definitions
> >> ************************************************
> >>
> >> // code I added here
> >> <--------------------------------------------------------------------------------
> >>
> >> void dbDumpRecords(DBBASE *pdbbase)
> >> {
> >> 	DBENTRY *pdbentry;
> >> 	long status;
> >>
> >> 	mypdbentry = dbAllocEntry(pdbbase);
> >>
> >> 	status = dbFirstRecordType(pdbentry);
> >> 	if(status) {printf("No record descriptions\n");return;}
> >> 	while(!status) {
> >> 		printf("\nRecord type:
> >> %s",dbGetRecordTypeName(pdbentry));
> >> 		status = dbFirstRecord(pdbentry);
> >> 		if(status) printf("   No Records\n");
> >> 		while(!status) {
> >> 			if (dbIsAlias(pdbentry)) {
> >> 				printf("\n  Alias:
> >> %s\n",dbGetRecordName(pdbentry));
> >> 			} else {
> >> 			printf("\n  Record:
> >> %s\n",dbGetRecordName(pdbentry));
> >> 			status = dbFirstField(pdbentry,TRUE);
> >> 				if(status) printf("    No Fields\n");
> >> 			while(!status) {
> >> 				printf("   %s:",dbGetFieldName(pdbentry));
> >> 				printf(" %s\n",dbGetString(pdbentry));	     //
> >> <-- if I comment out
> >> dbGetString the IOC doesn't crash,
> >> 				status=dbNextField(pdbentry,TRUE);           //
> >> so the function works
> >> to this point
> >> 				}
> >> 			}
> >> 			status = dbNextRecord(pdbentry);
> >> 		}
> >> 		status = dbNextRecordType(pdbentry);
> >> 	}
> >>
> >> 	printf("\nEnd of all Records\n");
> >>
> >> 	dbFreeEntry(pdbentry);
> >> }
> >> // end of function that I added
> >> <---------------------------------------------------------------------
> >>
> >> // Time the initialization process
> >> clock_t begin;
> >> clock_t end;
> >>
> >> /** @file iocMain.cpp
> >> 	The main program for the TwinCAT IOC.
> >>
> >>
> **************************************************************
> >> **********/
> >>
> >>
> >> bool debug;
> >>
> >> int main(int argc,char *argv[])
> >> {
> >> 	// Start timer
> >> 	begin = clock();
> >>
> >> 	// Run initialization
> >> 	if(argc>=2) {
> >>         iocsh(argv[1]);
> >>         epicsThreadSleep(.2);
> >>     }
> >>
> >> 	// Stop timer
> >> 	end = clock();
> >> 	printf("Initialization completed in %f seconds.\n",((float)(end -
> >> begin)/CLOCKS_PER_SEC));
> >>
> >>
> >> 	// Test routine
> >>
> **************************************************************
> >> ****
> >>
> >> 	// code I added
> >> <---------------------------------------------------------------------------------
> >>
> >> 	printf("\nRecords dump **********************\n");
> >>
> >> 	dbDumpRecords(*iocshPpdbbase);    // Trying to call function here!
> >>
> >> 	// end of code that I added
> >> <---------------------------------------------------------------------
> >>
> >> 	// EPICS command line
> >> 	iocsh(NULL);
> >>
> >> 	// Exit
> >> 	stopPLCs();
> >>     epicsExit(0);
> >>
> >> 	return(0);
> >> }
> >>
> >> To do a value comparison I think I'll need to use the runtime access
> >> routines in addition to some of the static routines. But at this point
> >> I'm
> >> not sure of anything. I have been trying to understand and copy code
> >> from
> >> the functions in dbtools.c and dbStaticLib.c but so far nothing has
> >> worked
> >> for me.
> >>
> >> I'm sorry to be such a problem, been staring at this for four weeks now
> >> and am at my wits end.
> >>
> >> Thank you in advance,
> >>
> >> Doug Lormand
> >>
> >> > Hi Doug,
> >> >
> >> >> The system is a Windows 7 computer! Unfortunately I need this to
> work
> >> in
> >> >> Windows because the software we use the IOC for is only Windows
> >> based.
> >> >> Thank you for pointing this out since I hadn't considered it could be
> >> a
> >> >> Windows compatibility issue. The ultimate goal is to use database
> >> access
> >> >> to compare values at boot up with a set of stored 'good' values. I
> >> think
> >> >> this will require the runtime database access routines which I've had
> >> >> some
> >> >> success with so far. So in the end I'm hoping this might be a non
> >> issue.
> >> >
> >> > Doing this on Windows should not be a problem. To clarify, you're
> >> > wanting to compare these values *before* the IOC runs iocInit()?
> >> >
> >> >>>> I have been able to get the example code to work within the IOC I'm
> >> >>>> trying
> >> >>>> to modify, but in a round about way. It is some type of pointer
> >> >>>> problem
> >> >>>> but I'm not sure what's wrong.
> >> >>>>
> >> >>>> So the code works if I add the following,
> >> >>>>
> >> >>>> void dbDumpRecords(DBBASE *pdbbase)
> >> >>>> {
> >> >>>>          DBENTRY *pdbentry;
> >> >>>>      long status;
> >> >>>>
> >> >>>>      status =
> >> >>>>
> >>
> dbReadDatabase(&pdbbase,"C:\\SlowControls\\EPICS\\Utilities\\Bin\\tCat.d
> >> bd",NULL,NULL);
> >> >>>>      if(!status) {printf("Database file loaded.\n");}
> >> >>>>      else {printf("Database load file failed.\n");}
> >> >>>>
> >> >>>>      status =
> >> >>>>
> >>
> dbReadDatabase(&pdbbase,"C:\\SlowControls\\EPICS\\Utilities\\Bin\\test.d
> >> b",NULL,NULL);
> >> >>>>      if(!status) {printf("Records file loaded.\n\n");}
> >> >>>>      else {printf("Records load file failed.\n\n");}
> >> >>>>
> >> >>>>          pdbentry = dbAllocEntry(pdbbase);
> >> >>>> .......rest of dump routine
> >> >>>>
> >> >>>> So the dump routine runs perfectly if I include dbReadDatabase
> >> >>>> routines
> >> >>>> for both the database.dbd and records.db files.
> >> >
> >> > What that is doing is loading a second instance of the database
> >> > definition into memory, which is not what you want to do.
> >> >
> >> >>>> What I don't understand is why I need to Read the databases into
> >> the
> >> >>>> function separately from the IOCs initialization. I thought I could
> >> >>>> access the runtime database in memory through pdbbase.
> >> >
> >> > You should be able to, so the fact that you're having problems tells
> >> me
> >> > that the pdbbase pointer that your code is using is not the same one
> >> > that the IOC is using. The dbStatic library is designed to allow
> >> > multiple databases to be loaded into memory at once, but the IOC can
> >> > only run one, which is declared in the header dbAccessDefs.h (also
> >> > included by dbAccess.h).
> >> >
> >> >>>>>> The code solution compiles without any issues but when I try to
> >> run
> >> >>>>>> the
> >> >>>> IOC it causes the following
> >> >>>>>> Unhandled exception at 0x5C6F1C6E (dbStaticHost.dll) in
> >> tcIoc.exe:
> >> >>>> 0xC0000005: Access violation reading location 0x00000031.
> >> >
> >> > That might have been that you were accessing iocshPpdbbase or
> pdbbase
> >> > before it was initialized. I'd need to see your iocMain.c to be sure,
> >> > but in general you should be running this kind of code from the
> >> startup
> >> > script using a command that your code registers with iocsh, or from an
> >> > initHook. That way it can be run at the right time, which would be
> >> after
> >> > the dbLoadDatabase() and dbLoadRecords() commands but before
> iocInit()
> >> > starts up the database operations.
> >> >
> >> >
> >> > Lets try starting from the beginning again: You're wanting to "compare
> >> > values at boot up with a set of stored 'good' values". As Tim said
> >> there
> >> > are some fields (mostly array fields) for which you can only do that
> >> > from an initHook as part of the IOC startup, but for most fields you
> >> can
> >> > do it earlier, as long as the database definition and record instances
> >> > have been loaded first.
> >> >
> >> > How & when are you running your code?
> >> >
> >> > - Andrew
> >> >
> >> > --
> >> > Light thinks it travels faster than anything but it is wrong.
> >> > No matter how fast light travels, it finds the darkness has
> >> > always got there first, and is waiting for it.
> >> >     -- Terry Pratchett, Reaper Man
> >> >
> >>
> >
> >
> 



References:
Re: Problems using static database routines to modify IOCs Dirk Zimoch
Re: Problems using static database routines to modify IOCs marc . lormand
RE: Problems using static database routines to modify IOCs Mooney, Tim M.
Re: Problems using static database routines to modify IOCs Andrew Johnson
Re: Problems using static database routines to modify IOCs marc . lormand
RE: Problems using static database routines to modify IOCs freddie.akeroyd
RE: Problems using static database routines to modify IOCs marc . lormand

Navigate by Date:
Prev: RE: Problems using static database routines to modify IOCs marc . lormand
Next: Final Program for the Spring 2015 EPICS Collaboration Meeting Maxwell, Dylan
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  <20152016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: RE: Problems using static database routines to modify IOCs marc . lormand
Next: Gentec S-link power meter problem with ending I/O interrupt measurement bohmm
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  <20152016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 16 Dec 2015 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·