From 5783823e251bf00479dccdef771057720c32d01f Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 23 Feb 2017 20:08:46 -0500 Subject: [PATCH 01/12] libCom: revise ipAddrToAscii create multiple light-weight engines to track transactions by engine and cancel all transactions when an engine is released. prior to fix for lp:1527636 this was ensured for the last/only owner for the engine singleton. --- src/libCom/misc/ipAddrToAsciiAsynchronous.cpp | 250 ++++++++++++------ src/libCom/misc/ipAddrToAsciiAsynchronous.h | 4 + 2 files changed, 174 insertions(+), 80 deletions(-) diff --git a/src/libCom/misc/ipAddrToAsciiAsynchronous.cpp b/src/libCom/misc/ipAddrToAsciiAsynchronous.cpp index 6dbdc405e..c6fea15b4 100644 --- a/src/libCom/misc/ipAddrToAsciiAsynchronous.cpp +++ b/src/libCom/misc/ipAddrToAsciiAsynchronous.cpp @@ -18,6 +18,9 @@ #include #include +//#define EPICS_FREELIST_DEBUG +#define EPICS_PRIVATE_API + #define epicsExportSharedSymbols #include "ipAddrToAsciiAsynchronous.h" #include "epicsThread.h" @@ -45,7 +48,6 @@ public: < ipAddrToAsciiTransactionPrivate, 0x80 > & ); epicsPlacementDeleteOperator (( void *, tsFreeList < ipAddrToAsciiTransactionPrivate, 0x80 > & )) -private: osiSockAddr addr; ipAddrToAsciiEnginePrivate & engine; ipAddrToAsciiCallBack * pCB; @@ -54,7 +56,7 @@ private: void release (); void * operator new ( size_t ); void operator delete ( void * ); - friend class ipAddrToAsciiEnginePrivate; +private: ipAddrToAsciiTransactionPrivate & operator = ( const ipAddrToAsciiTransactionPrivate & ); ipAddrToAsciiTransactionPrivate ( const ipAddrToAsciiTransactionPrivate & ); }; @@ -75,41 +77,54 @@ extern "C" { static void ipAddrToAsciiEngineGlobalMutexConstruct ( void * ); } -// - this class executes the synchronous DNS query -// - it creates one thread -class ipAddrToAsciiEnginePrivate : - public ipAddrToAsciiEngine, - public epicsThreadRunable { -public: - ipAddrToAsciiEnginePrivate (); - virtual ~ipAddrToAsciiEnginePrivate (); - void show ( unsigned level ) const; -private: +namespace { +struct ipAddrToAsciiGlobal : public epicsThreadRunable { + ipAddrToAsciiGlobal(); + virtual ~ipAddrToAsciiGlobal() {} + + virtual void run (); + char nameTmp [1024]; - tsFreeList - < ipAddrToAsciiTransactionPrivate, 0x80 > + tsFreeList + < ipAddrToAsciiTransactionPrivate, 0x80 > transactionFreeList; tsDLList < ipAddrToAsciiTransactionPrivate > labor; mutable epicsMutex mutex; epicsEvent laborEvent; epicsEvent destructorBlockEvent; epicsThread thread; + // pCurrent may be changed by any thread (worker or other) ipAddrToAsciiTransactionPrivate * pCurrent; + // pActive may only be changed by the worker + ipAddrToAsciiTransactionPrivate * pActive; unsigned cancelPendingCount; bool exitFlag; bool callbackInProgress; - static ipAddrToAsciiEnginePrivate * pEngine; +}; +} + +// - this class executes the synchronous DNS query +// - it creates one thread +class ipAddrToAsciiEnginePrivate : + public ipAddrToAsciiEngine { +public: + ipAddrToAsciiEnginePrivate() :refcount(1u), released(false) {} + virtual ~ipAddrToAsciiEnginePrivate () {} + void show ( unsigned level ) const; + + unsigned refcount; + bool released; + + static ipAddrToAsciiGlobal * pEngine; ipAddrToAsciiTransaction & createTransaction (); - void release (); - void run (); - ipAddrToAsciiEnginePrivate ( const ipAddrToAsciiEngine & ); + void release (); + +private: + ipAddrToAsciiEnginePrivate ( const ipAddrToAsciiEngine & ); ipAddrToAsciiEnginePrivate & operator = ( const ipAddrToAsciiEngine & ); - friend class ipAddrToAsciiEngine; - friend class ipAddrToAsciiTransactionPrivate; - friend void ipAddrToAsciiEngineGlobalMutexConstruct ( void * ); }; -ipAddrToAsciiEnginePrivate * ipAddrToAsciiEnginePrivate :: pEngine = 0; +ipAddrToAsciiGlobal * ipAddrToAsciiEnginePrivate :: pEngine = 0; static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = EPICS_THREAD_ONCE_INIT; // the users are not required to supply a show routine @@ -124,12 +139,24 @@ ipAddrToAsciiEngine::~ipAddrToAsciiEngine () {} static void ipAddrToAsciiEngineGlobalMutexConstruct ( void * ) { try{ - ipAddrToAsciiEnginePrivate::pEngine = new ipAddrToAsciiEnginePrivate (); + ipAddrToAsciiEnginePrivate::pEngine = new ipAddrToAsciiGlobal (); }catch(std::exception& e){ errlogPrintf("ipAddrToAsciiEnginePrivate ctor fails with: %s\n", e.what()); } } +void ipAddrToAsciiEngine::cleanup() +{ + { + epicsGuard G(ipAddrToAsciiEnginePrivate::pEngine->mutex); + ipAddrToAsciiEnginePrivate::pEngine->exitFlag = true; + } + ipAddrToAsciiEnginePrivate::pEngine->laborEvent.signal(); + ipAddrToAsciiEnginePrivate::pEngine->thread.exitWait(); + delete ipAddrToAsciiEnginePrivate::pEngine; + ipAddrToAsciiEnginePrivate::pEngine = 0; +} + // for now its probably sufficent to allocate one // DNS transaction thread for all codes sharing // the same process that need DNS services but we @@ -141,41 +168,78 @@ ipAddrToAsciiEngine & ipAddrToAsciiEngine::allocate () ipAddrToAsciiEngineGlobalMutexConstruct, 0 ); if(!ipAddrToAsciiEnginePrivate::pEngine) throw std::runtime_error("ipAddrToAsciiEngine::allocate fails"); - return * ipAddrToAsciiEnginePrivate::pEngine; + return * new ipAddrToAsciiEnginePrivate(); } -ipAddrToAsciiEnginePrivate::ipAddrToAsciiEnginePrivate () : +ipAddrToAsciiGlobal::ipAddrToAsciiGlobal () : thread ( *this, "ipToAsciiProxy", epicsThreadGetStackSize(epicsThreadStackBig), epicsThreadPriorityLow ), - pCurrent ( 0 ), cancelPendingCount ( 0u ), exitFlag ( false ), + pCurrent ( 0 ), pActive ( 0 ), cancelPendingCount ( 0u ), exitFlag ( false ), callbackInProgress ( false ) { this->thread.start (); // start the thread } -ipAddrToAsciiEnginePrivate::~ipAddrToAsciiEnginePrivate () -{ - { - epicsGuard < epicsMutex > guard ( this->mutex ); - this->exitFlag = true; - } - this->laborEvent.signal (); - this->thread.exitWait (); -} void ipAddrToAsciiEnginePrivate::release () { + bool last; + { + epicsGuard < epicsMutex > guard ( this->pEngine->mutex ); + if(released) + throw std::logic_error("Engine release() called again!"); + + // released==true prevents new transactions + released = true; + + { + // cancel any pending transactions + tsDLIter < ipAddrToAsciiTransactionPrivate > it(pEngine->labor.firstIter()); + while(it.valid()) { + ipAddrToAsciiTransactionPrivate *trn = it.pointer(); + ++it; + + if(this==&trn->engine) { + trn->pending = false; + pEngine->labor.remove(*trn); + } + } + + // cancel transaction in lookup or callback + if (pEngine->pCurrent && this==&pEngine->pCurrent->engine) { + pEngine->pCurrent->pending = false; + pEngine->pCurrent = 0; + } + + // wait for completion of in-progress callback + pEngine->cancelPendingCount++; + while(pEngine->pActive && this==&pEngine->pActive->engine + && ! pEngine->thread.isCurrentThread()) { + epicsGuardRelease < epicsMutex > unguard ( guard ); + pEngine->destructorBlockEvent.wait(); + } + pEngine->cancelPendingCount--; + if(pEngine->cancelPendingCount) + pEngine->destructorBlockEvent.signal(); + } + + assert(refcount>0); + last = 0==--refcount; + } + if(last) { + delete this; + } } void ipAddrToAsciiEnginePrivate::show ( unsigned level ) const { - epicsGuard < epicsMutex > guard ( this->mutex ); + epicsGuard < epicsMutex > guard ( this->pEngine->mutex ); printf ( "ipAddrToAsciiEngine at %p with %u requests pending\n", - static_cast (this), this->labor.count () ); + static_cast (this), this->pEngine->labor.count () ); if ( level > 0u ) { - tsDLIterConst < ipAddrToAsciiTransactionPrivate > - pItem = this->labor.firstIter (); + tsDLIter < ipAddrToAsciiTransactionPrivate > + pItem = this->pEngine->labor.firstIter (); while ( pItem.valid () ) { pItem->show ( level - 1u ); pItem++; @@ -183,10 +247,10 @@ void ipAddrToAsciiEnginePrivate::show ( unsigned level ) const } if ( level > 1u ) { printf ( "mutex:\n" ); - this->mutex.show ( level - 2u ); + this->pEngine->mutex.show ( level - 2u ); printf ( "laborEvent:\n" ); - this->laborEvent.show ( level - 2u ); - printf ( "exitFlag boolean = %u\n", this->exitFlag ); + this->pEngine->laborEvent.show ( level - 2u ); + printf ( "exitFlag boolean = %u\n", this->pEngine->exitFlag ); printf ( "exit event:\n" ); } } @@ -226,10 +290,20 @@ void ipAddrToAsciiTransactionPrivate::operator delete ( void * ) ipAddrToAsciiTransaction & ipAddrToAsciiEnginePrivate::createTransaction () { - return * new ( this->transactionFreeList ) ipAddrToAsciiTransactionPrivate ( *this ); + epicsGuard G(this->pEngine->mutex); + if(this->released) + throw std::logic_error("createTransaction() on release()'d ipAddrToAsciiEngine"); + + assert(this->refcount>0); + + ipAddrToAsciiTransactionPrivate *ret = new ( this->pEngine->transactionFreeList ) ipAddrToAsciiTransactionPrivate ( *this ); + + this->refcount++; + + return * ret; } -void ipAddrToAsciiEnginePrivate::run () +void ipAddrToAsciiGlobal::run () { epicsGuard < epicsMutex > guard ( this->mutex ); while ( ! this->exitFlag ) { @@ -267,7 +341,7 @@ void ipAddrToAsciiEnginePrivate::run () // fix for lp:1580623 // a destructing cac sets pCurrent to NULL, so // make local copy to avoid race when releasing the guard - ipAddrToAsciiTransactionPrivate *pCur = this->pCurrent; + ipAddrToAsciiTransactionPrivate *pCur = pActive = pCurrent; this->callbackInProgress = true; { @@ -277,6 +351,7 @@ void ipAddrToAsciiEnginePrivate::run () } this->callbackInProgress = false; + pActive = 0; if ( this->pCurrent ) { this->pCurrent->pending = false; @@ -300,44 +375,53 @@ ipAddrToAsciiTransactionPrivate::ipAddrToAsciiTransactionPrivate void ipAddrToAsciiTransactionPrivate::release () { this->~ipAddrToAsciiTransactionPrivate (); - this->engine.transactionFreeList.release ( this ); + this->engine.pEngine->transactionFreeList.release ( this ); } ipAddrToAsciiTransactionPrivate::~ipAddrToAsciiTransactionPrivate () { - epicsGuard < epicsMutex > guard ( this->engine.mutex ); - while ( this->pending ) { - if ( this->engine.pCurrent == this && - this->engine.callbackInProgress && - ! this->engine.thread.isCurrentThread() ) { - // cancel from another thread while callback in progress - // waits for callback to complete - assert ( this->engine.cancelPendingCount < UINT_MAX ); - this->engine.cancelPendingCount++; - { - epicsGuardRelease < epicsMutex > unguard ( guard ); - this->engine.destructorBlockEvent.wait (); - } - assert ( this->engine.cancelPendingCount > 0u ); - this->engine.cancelPendingCount--; - if ( ! this->pending ) { - if ( this->engine.cancelPendingCount ) { - this->engine.destructorBlockEvent.signal (); + ipAddrToAsciiGlobal *pGlobal = this->engine.pEngine; + bool last; + { + epicsGuard < epicsMutex > guard ( pGlobal->mutex ); + while ( this->pending ) { + if ( pGlobal->pCurrent == this && + pGlobal->callbackInProgress && + ! pGlobal->thread.isCurrentThread() ) { + // cancel from another thread while callback in progress + // waits for callback to complete + assert ( pGlobal->cancelPendingCount < UINT_MAX ); + pGlobal->cancelPendingCount++; + { + epicsGuardRelease < epicsMutex > unguard ( guard ); + pGlobal->destructorBlockEvent.wait (); + } + assert ( pGlobal->cancelPendingCount > 0u ); + pGlobal->cancelPendingCount--; + if ( ! this->pending ) { + if ( pGlobal->cancelPendingCount ) { + pGlobal->destructorBlockEvent.signal (); + } + break; } - break; - } - } - else { - if ( this->engine.pCurrent == this ) { - // cancel from callback, or while lookup in progress - this->engine.pCurrent = 0; } else { - // cancel before lookup starts - this->engine.labor.remove ( *this ); + if ( pGlobal->pCurrent == this ) { + // cancel from callback, or while lookup in progress + pGlobal->pCurrent = 0; + } + else { + // cancel before lookup starts + pGlobal->labor.remove ( *this ); + } + this->pending = false; } - this->pending = false; } + assert(this->engine.refcount>0); + last = 0==--this->engine.refcount; + } + if(last) { + delete &this->engine; } } @@ -345,15 +429,21 @@ void ipAddrToAsciiTransactionPrivate::ipAddrToAscii ( const osiSockAddr & addrIn, ipAddrToAsciiCallBack & cbIn ) { bool success; + ipAddrToAsciiGlobal *pGlobal = this->engine.pEngine; { - epicsGuard < epicsMutex > guard ( this->engine.mutex ); - // put some reasonable limit on queue expansion - if ( !this->pending && engine.labor.count () < 16u ) { + epicsGuard < epicsMutex > guard ( pGlobal->mutex ); + + if (this->engine.released) { + errlogPrintf("Warning: ipAddrToAscii on transaction with release()'d ipAddrToAsciiEngine"); + success = false; + + } else if ( !this->pending && pGlobal->labor.count () < 16u ) { + // put some reasonable limit on queue expansion this->addr = addrIn; this->pCB = & cbIn; this->pending = true; - this->engine.labor.add ( *this ); + pGlobal->labor.add ( *this ); success = true; } else { @@ -362,7 +452,7 @@ void ipAddrToAsciiTransactionPrivate::ipAddrToAscii ( } if ( success ) { - this->engine.laborEvent.signal (); + pGlobal->laborEvent.signal (); } else { char autoNameTmp[256]; @@ -379,7 +469,7 @@ osiSockAddr ipAddrToAsciiTransactionPrivate::address () const void ipAddrToAsciiTransactionPrivate::show ( unsigned level ) const { - epicsGuard < epicsMutex > guard ( this->engine.mutex ); + epicsGuard < epicsMutex > guard ( this->engine.pEngine->mutex ); char ipAddr [64]; sockAddrToDottedIP ( &this->addr.sa, ipAddr, sizeof ( ipAddr ) ); printf ( "ipAddrToAsciiTransactionPrivate for address %s\n", ipAddr ); diff --git a/src/libCom/misc/ipAddrToAsciiAsynchronous.h b/src/libCom/misc/ipAddrToAsciiAsynchronous.h index f2de879b6..5da06860a 100644 --- a/src/libCom/misc/ipAddrToAsciiAsynchronous.h +++ b/src/libCom/misc/ipAddrToAsciiAsynchronous.h @@ -44,6 +44,10 @@ public: static ipAddrToAsciiEngine & allocate (); protected: virtual ~ipAddrToAsciiEngine () = 0; +public: +#ifdef EPICS_PRIVATE_API + static void cleanup(); +#endif }; #endif // ifdef ipAddrToAsciiAsynchronous_h From 048b75304d73446eb581c87e294cd1f3c4eff528 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sat, 25 Feb 2017 19:08:46 -0500 Subject: [PATCH 02/12] libCom/test: add ipAddrToAsciiTest --- src/libCom/test/Makefile | 3 + src/libCom/test/ipAddrToAsciiTest.cpp | 161 ++++++++++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 src/libCom/test/ipAddrToAsciiTest.cpp diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile index 5f486938f..b79eb11e8 100644 --- a/src/libCom/test/Makefile +++ b/src/libCom/test/Makefile @@ -151,6 +151,9 @@ epicsMessageQueueTest_SRCS += epicsMessageQueueTest.cpp testHarness_SRCS += epicsMessageQueueTest.cpp TESTS += epicsMessageQueueTest +TESTPROD_HOST += ipAddrToAsciiTest +ipAddrToAsciiTest_SRCS += ipAddrToAsciiTest.cpp +TESTS += ipAddrToAsciiTest # The testHarness runs all the test programs in a known working order. testHarness_SRCS += epicsRunLibComTests.c diff --git a/src/libCom/test/ipAddrToAsciiTest.cpp b/src/libCom/test/ipAddrToAsciiTest.cpp new file mode 100644 index 000000000..c17c1a7cd --- /dev/null +++ b/src/libCom/test/ipAddrToAsciiTest.cpp @@ -0,0 +1,161 @@ +/*************************************************************************\ +* Copyright (c) 2017 Michael Davidsaver +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. +\*************************************************************************/ + +#include +#include + +#define EPICS_PRIVATE_API + +#include "epicsMutex.h" +#include "epicsGuard.h" +#include "epicsThread.h" +#include "epicsEvent.h" +#include "ipAddrToAsciiAsynchronous.h" + +#include "epicsUnitTest.h" +#include "testMain.h" + +namespace { + +typedef epicsGuard Guard; +typedef epicsGuardRelease UnGuard; + +struct CB : public ipAddrToAsciiCallBack +{ + const char *name; + epicsMutex mutex; + epicsEvent starter, blocker, complete; + bool started, cont, done; + CB(const char *name) : name(name), started(false), cont(false), done(false) {} + virtual ~CB() {} + virtual void transactionComplete ( const char * pHostName ) + { + Guard G(mutex); + started = true; + starter.signal(); + testDiag("In transactionComplete(%s) for %s", pHostName, name); + while(!cont) { + UnGuard U(G); + if(!blocker.wait(2.0)) + break; + } + done = true; + complete.signal(); + } + void waitStart() + { + Guard G(mutex); + while(!started) { + UnGuard U(G); + if(!starter.wait(2.0)) + break; + } + } + void poke() + { + testDiag("Poke"); + Guard G(mutex); + cont = true; + blocker.signal(); + } + void finish() + { + testDiag("Finish"); + Guard G(mutex); + while(!done) { + UnGuard U(G); + if(!complete.wait(2.0)) + break; + } + testDiag("Finished"); + } +}; + +// ensure that lookup of 127.0.0.1 works +void doLookup(ipAddrToAsciiEngine& engine) +{ + testDiag("In doLookup"); + + ipAddrToAsciiTransaction& trn(engine.createTransaction()); + CB cb("cb"); + osiSockAddr addr; + addr.ia.sin_family = AF_INET; + addr.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.ia.sin_port = htons(42); + + testDiag("Start lookup"); + trn.ipAddrToAscii(addr, cb); + cb.poke(); + cb.finish(); + testOk1(cb.cont); + testOk1(cb.done); + + trn.release(); +} + +// Test cancel of pending transaction +void doCancel() +{ + testDiag("In doCancel"); + + ipAddrToAsciiEngine& engine1(ipAddrToAsciiEngine::allocate()); + ipAddrToAsciiEngine& engine2(ipAddrToAsciiEngine::allocate()); + + ipAddrToAsciiTransaction& trn1(engine1.createTransaction()), + & trn2(engine2.createTransaction()); + testOk1(&trn1!=&trn2); + CB cb1("cb1"), cb2("cb2"); + + osiSockAddr addr; + addr.ia.sin_family = AF_INET; + addr.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.ia.sin_port = htons(42); + + // ensure that the worker thread is blocked with a transaction from engine1 + testDiag("Start lookup1"); + trn1.ipAddrToAscii(addr, cb1); + testDiag("Wait start1"); + cb1.waitStart(); + + testDiag("Start lookup2"); + trn2.ipAddrToAscii(addr, cb2); + + testDiag("release engine2, implicitly cancels lookup2"); + engine2.release(); + + cb2.poke(); + testDiag("Wait for lookup2 timeout"); + cb2.finish(); + testOk1(!cb2.done); + + testDiag("Complete lookup1"); + cb1.poke(); + cb1.finish(); + testOk1(cb1.done); + + engine1.release(); + + trn1.release(); + trn2.release(); +} + +} // namespace + +MAIN(ipAddrToAsciiTest) +{ + testPlan(5); + { + ipAddrToAsciiEngine& engine(ipAddrToAsciiEngine::allocate()); + doLookup(engine); + engine.release(); + } + doCancel(); + // TODO: somehow test cancel of in-progress callback + // allow time for any un-canceled transcations to crash us... + epicsThreadSleep(1.0); + ipAddrToAsciiEngine::cleanup(); + return testDone(); +} From f164b14ba11272864910a539aea9c35e5b44f85b Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Thu, 30 Mar 2017 17:08:00 +0200 Subject: [PATCH 03/12] Moved .bzrignore to .gitignore --- .bzrignore | 9 --------- .gitignore | 11 +++++++++++ 2 files changed, 11 insertions(+), 9 deletions(-) delete mode 100644 .bzrignore create mode 100644 .gitignore diff --git a/.bzrignore b/.bzrignore deleted file mode 100644 index df0e03ed6..000000000 --- a/.bzrignore +++ /dev/null @@ -1,9 +0,0 @@ -./bin -./lib -./db -./dbd -./html -./include -./templates -**/O.* -./QtC-* diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..a8499e2f2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +/bin/ +/lib/ +/db/ +/dbd/ +/html/ +/include/ +/templates/ +O.* +/QtC-* +*.orig +*.log From 5726ca696423252f08c2ee8dda1a8e38e3d772fa Mon Sep 17 00:00:00 2001 From: Ralph Lange Date: Fri, 31 Mar 2017 15:01:51 +0200 Subject: [PATCH 04/12] libCom/test: add network libraries for Windows builds --- src/libCom/test/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile index b79eb11e8..6800b5cdf 100644 --- a/src/libCom/test/Makefile +++ b/src/libCom/test/Makefile @@ -11,6 +11,7 @@ TOP=../../.. include $(TOP)/configure/CONFIG PROD_LIBS += Com +PROD_SYS_LIBS_WIN32 += ws2_32 advapi32 user32 TESTPROD_HOST += epicsUnitTestTest epicsUnitTestTest_SRCS += epicsUnitTestTest.c From e0af3e2af502ce16cc352e5f5b6b55b26213d5a5 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 31 Mar 2017 12:08:03 -0500 Subject: [PATCH 05/12] Adjusted .gitignore patterns --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a8499e2f2..c3040f162 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/cfg/ /bin/ /lib/ /db/ @@ -5,7 +6,7 @@ /html/ /include/ /templates/ -O.* +O.*/ /QtC-* *.orig *.log From 352fd32c457f6f94835d3f56b2b3d72426d04dde Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Wed, 12 Apr 2017 20:30:23 -0400 Subject: [PATCH 06/12] libCom/test: add ipAddrToAsciiTest to testHarness --- src/libCom/test/Makefile | 1 + src/libCom/test/epicsRunLibComTests.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile index 6800b5cdf..6239e0b41 100644 --- a/src/libCom/test/Makefile +++ b/src/libCom/test/Makefile @@ -154,6 +154,7 @@ TESTS += epicsMessageQueueTest TESTPROD_HOST += ipAddrToAsciiTest ipAddrToAsciiTest_SRCS += ipAddrToAsciiTest.cpp +testHarness_SRCS += ipAddrToAsciiTest.cpp TESTS += ipAddrToAsciiTest # The testHarness runs all the test programs in a known working order. diff --git a/src/libCom/test/epicsRunLibComTests.c b/src/libCom/test/epicsRunLibComTests.c index 81290644a..16d316592 100644 --- a/src/libCom/test/epicsRunLibComTests.c +++ b/src/libCom/test/epicsRunLibComTests.c @@ -41,6 +41,7 @@ int macEnvExpandTest(void); int ringPointerTest(void); int ringBytesTest(void); int blockingSockTest(void); +int ipAddrToAsciiTest(void); int epicsSockResolveTest(void); int taskwdTest(void); int epicsExitTest(void); @@ -102,6 +103,8 @@ void epicsRunLibComTests(void) runTest(ringBytesTest); runTest(blockingSockTest); + + runTest(ipAddrToAsciiTest); runTest(epicsSockResolveTest); From 1f90e984918f9ef169570ae79b37ee605284255f Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sat, 15 Apr 2017 19:34:04 -0400 Subject: [PATCH 07/12] libCom/test: ipAddrToAsciiTest skip cleanup unless valgrind is possible --- src/libCom/test/ipAddrToAsciiTest.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libCom/test/ipAddrToAsciiTest.cpp b/src/libCom/test/ipAddrToAsciiTest.cpp index c17c1a7cd..0999555b6 100644 --- a/src/libCom/test/ipAddrToAsciiTest.cpp +++ b/src/libCom/test/ipAddrToAsciiTest.cpp @@ -7,6 +7,8 @@ #include #include +#include + #define EPICS_PRIVATE_API #include "epicsMutex.h" @@ -156,6 +158,10 @@ MAIN(ipAddrToAsciiTest) // TODO: somehow test cancel of in-progress callback // allow time for any un-canceled transcations to crash us... epicsThreadSleep(1.0); + +#ifndef NVALGRIND ipAddrToAsciiEngine::cleanup(); +#endif + return testDone(); } From 0c02c5cb30c7e1e384b6438a8e78e0fec65ac771 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Sat, 15 Apr 2017 19:38:56 -0400 Subject: [PATCH 08/12] update notes --- documentation/RELEASE_NOTES.html | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 859ff7b29..b2465e53c 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -13,6 +13,12 @@ +

Fix DNS related crash on exit

+ +

The attempt to fix DNS related delays for short lived CLI programs (eg. caget) +in lp:1527636 introduced a bug which cased these short lived clients to crash on exit. +This bug should now be fixed.

+

Server bind issue on Windows

When a National Instruments network variables CA server is already running on From d4552af39b5006aa5f3a9d2d0c67411464ec54b9 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Mon, 17 Apr 2017 11:47:21 -0500 Subject: [PATCH 09/12] Fix and test for macLib losing error status Problem found & diagnosed by Mark Rivers. --- src/libCom/macLib/macCore.c | 4 ++-- src/libCom/test/macLibTest.c | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libCom/macLib/macCore.c b/src/libCom/macLib/macCore.c index f550ed7dc..ba1c84fa4 100644 --- a/src/libCom/macLib/macCore.c +++ b/src/libCom/macLib/macCore.c @@ -857,9 +857,9 @@ static void refer ( MAC_HANDLE *handle, MAC_ENTRY *entry, int level, if ( !refentry->visited ) { /* reference is good, use it */ if ( !handle->dirty ) { - /* copy the already-expanded value, and its error status! */ + /* copy the already-expanded value, merge any error status */ cpy2val( refentry->value, &v, valend ); - entry->error = refentry->error; + entry->error = entry->error || refentry->error; } else { /* translate raw value */ const char *rv = refentry->rawval; diff --git a/src/libCom/test/macLibTest.c b/src/libCom/test/macLibTest.c index 1f00a6ac7..7f1e2c544 100644 --- a/src/libCom/test/macLibTest.c +++ b/src/libCom/test/macLibTest.c @@ -65,7 +65,7 @@ static void ovcheck(void) MAIN(macLibTest) { - testPlan(89); + testPlan(91); if (macCreateHandle(&h, NULL)) testAbort("macCreateHandle() failed"); @@ -203,6 +203,9 @@ MAIN(macLibTest) /* STR2 = "VAL2" */ check("${FOO}", " VAL2"); + check("$(FOO)$(FOO1)", "!VAL2$(FOO1,undefined)"); + check("$(FOO1)$(FOO)", "!$(FOO1,undefined)VAL2"); + macPutValue(h, "BAR","${FOO}"); /* FOO = "${BAR}" */ /* BAR = "${FOO}" */ From aca7b44a0556d741f5c54e3c8d6507028c5ad26a Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 20 Apr 2017 11:42:52 -0500 Subject: [PATCH 10/12] Supress MS warning C4251 --- configure/os/CONFIG.win32-x86.win32-x86 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/configure/os/CONFIG.win32-x86.win32-x86 b/configure/os/CONFIG.win32-x86.win32-x86 index 022f80736..863841923 100644 --- a/configure/os/CONFIG.win32-x86.win32-x86 +++ b/configure/os/CONFIG.win32-x86.win32-x86 @@ -101,11 +101,12 @@ CODE_CPPFLAGS += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE # Compiler flags for C++ files # -# -W use warning level N -# (maximum lint level warnings at level 4) -# -w44355 set "'this' used in the base initializer list" to be level 4 +# -W disable warnings from levels > n +# -w set warning m to level n +# -w44355 "'this' used in the base initializer list" # -w44344 "behavior change: use of explicit template arguments results in ..." -WARN_CXXFLAGS_YES = -W3 -w44355 -w44344 +# -w44251 "class needs to have dll-interface to be used by clients of ..." +WARN_CXXFLAGS_YES = -W3 -w44355 -w44344 -w44251 WARN_CXXFLAGS_NO = -W1 # From 9f01c475421ccfcad25607773e2d9b72a002bce3 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 20 Apr 2017 16:23:36 -0500 Subject: [PATCH 11/12] Allow whitespace before comments in AS config files Fixes lp: #1677302 Makes the lexer patterns more like dbStatic. Handle non-printable invalid characters in input properly. --- src/as/asLib_lex.l | 52 ++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/src/as/asLib_lex.l b/src/as/asLib_lex.l index 5e0451925..924105c14 100644 --- a/src/as/asLib_lex.l +++ b/src/as/asLib_lex.l @@ -3,18 +3,21 @@ * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ -digit [0-9] -name [a-zA-Z0-9_\-:\.\[\]<>;] -notquote [^\"] -escapequote \\\" -string {notquote}|{escapequote} +newline "\n" +backslash "\\" +doublequote "\"" +comment "#" whitespace [ \t\r] +escape {backslash}. +stringchar [^"\n\\] + +name [a-zA-Z0-9_\-+:.\[\]<>;] +digit [0-9] punctuation [(){},] -link [A-L] +link [A-L] %{ static ASINPUTFUNCPTR *my_yyinput; @@ -37,46 +40,55 @@ HAG { return(tokenHAG); } ASG { return(tokenASG); } RULE { return(tokenRULE); } CALC { return(tokenCALC); } + INP{link} { yylval.Int = (unsigned char)yytext[3]; yylval.Int -= 'A'; return(tokenINP); - } +} {digit}+ { /*integer*/ yylval.Int = atoi((char *)yytext); return(tokenINTEGER); - } +} {name}+ { /*unquoted string*/ yylval.Str=asStrdup(yytext); return(tokenSTRING); - } +} -\"{string}*\" { /*quoted string*/ - /* making sure that neither double quote gets passed back */ +{doublequote}({stringchar}|{escape})*{doublequote} { /* quoted string */ yylval.Str=asStrdup(yytext+1); yylval.Str[strlen(yylval.Str)-1] = '\0'; return(tokenSTRING); - } +} + +{doublequote}({stringchar}|{escape})*{newline} { /* bad string */ + yyerror("Newline in quoted string, closing quote missing"); +} {punctuation} { return(yytext[0]); } -^#.* -{whitespace} ; +{newline} { line_num++; } -\n { line_num ++;} +{comment}.* ; +{whitespace} ; . { char message[40]; YY_BUFFER_STATE *dummy=0; - sprintf(message,"invalid character '%c'",yytext[0]); + if (isprint((int) yytext[0])) { + sprintf(message, "Invalid character '%c'", yytext[0]); + } + else { + sprintf(message, "Invalid character 0x%2.2x", yytext[0]); + } yyerror(message); /*The following suppress compiler warning messages*/ if (0) yyunput('c',(unsigned char *) message); if (0) yy_switch_to_buffer(*dummy); - } +} %% From 64c16c0f6e7fecb4a65c059efff005067541630a Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 20 Apr 2017 16:27:20 -0500 Subject: [PATCH 12/12] Cleanup in asLib Improve error messages. Remove unnecessary pointer casts. --- src/as/asLib.y | 16 ++- src/as/asLibRoutines.c | 276 +++++++++++++++++++++-------------------- 2 files changed, 146 insertions(+), 146 deletions(-) diff --git a/src/as/asLib.y b/src/as/asLib.y index 7e2803158..55d48ebad 100644 --- a/src/as/asLib.y +++ b/src/as/asLib.y @@ -3,9 +3,8 @@ * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ %{ static int yyerror(char *); @@ -29,9 +28,7 @@ static ASGRULE *yyAsgRule=NULL; %union { int Int; - char Char; char *Str; - double Real; } %% @@ -208,11 +205,12 @@ rule_hag_list_name: tokenSTRING static int yyerror(char *str) { - if (strlen(str)) epicsPrintf("%s\n", str); - epicsPrintf("Access Security file error at line %d\n", - line_num); + if (strlen(str)) + errlogPrintf("%s at line %d\n", str, line_num); + else + errlogPrintf("Error at line %d\n", line_num); yyFailed = TRUE; - return(0); + return 0; } static int myParse(ASINPUTFUNCPTR inputfunction) { diff --git a/src/as/asLibRoutines.c b/src/as/asLibRoutines.c index 2a5c0d798..be3f1e2ef 100644 --- a/src/as/asLibRoutines.c +++ b/src/as/asLibRoutines.c @@ -1,12 +1,10 @@ -/* share/src/as/asLibRoutines.c */ /*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. -* EPICS BASE Versions 3.13.7 -* and higher are distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* EPICS BASE is distributed subject to a Software License Agreement found +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* Author: Marty Kraimer Date: 10-15-93 */ @@ -21,7 +19,7 @@ #include "epicsThread.h" #include "cantProceed.h" #include "epicsMutex.h" -#include "epicsPrint.h" +#include "errlog.h" #include "gpHash.h" #include "freeList.h" #include "macLib.h" @@ -111,7 +109,7 @@ long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction) pasg = (ASG *)ellFirst(&pasbasenew->asgList); while(pasg) { pasg->pavalue = asCalloc(CALCPERFORM_NARGS, sizeof(double)); - pasg = (ASG *)ellNext((ELLNODE *)pasg); + pasg = (ASG *)ellNext(&pasg->node); } gphInitPvt(&pasbasenew->phash, 256); /*Hash each uagname and each hagname*/ @@ -121,12 +119,12 @@ long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction) while(puagname) { pgphentry = gphAdd(pasbasenew->phash,puagname->user,puag); if(!pgphentry) { - epicsPrintf("Duplicated user '%s' in UAG '%s'\n", + errlogPrintf("Duplicated user '%s' in UAG '%s'\n", puagname->user, puag->name); } - puagname = (UAGNAME *)ellNext((ELLNODE *)puagname); + puagname = (UAGNAME *)ellNext(&puagname->node); } - puag = (UAG *)ellNext((ELLNODE *)puag); + puag = (UAG *)ellNext(&puag->node); } phag = (HAG *)ellFirst(&pasbasenew->hagList); while(phag) { @@ -134,12 +132,12 @@ long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction) while(phagname) { pgphentry = gphAdd(pasbasenew->phash,phagname->host,phag); if(!pgphentry) { - epicsPrintf("Duplicated host '%s' in HAG '%s'\n", + errlogPrintf("Duplicated host '%s' in HAG '%s'\n", phagname->host, phag->name); } - phagname = (HAGNAME *)ellNext((ELLNODE *)phagname); + phagname = (HAGNAME *)ellNext(&phagname->node); } - phag = (HAG *)ellNext((ELLNODE *)phag); + phag = (HAG *)ellNext(&phag->node); } pasbaseold = (ASBASE *)pasbase; pasbase = (ASBASE volatile *)pasbasenew; @@ -152,12 +150,12 @@ long epicsShareAPI asInitialize(ASINPUTFUNCPTR inputfunction) while(poldasg) { poldmem = (ASGMEMBER *)ellFirst(&poldasg->memberList); while(poldmem) { - pnextoldmem = (ASGMEMBER *)ellNext((ELLNODE *)poldmem); - ellDelete(&poldasg->memberList,(ELLNODE *)poldmem); + pnextoldmem = (ASGMEMBER *)ellNext(&poldmem->node); + ellDelete(&poldasg->memberList,&poldmem->node); status = asAddMemberPvt(&poldmem,poldmem->asgName); poldmem = pnextoldmem; } - poldasg = (ASG *)ellNext((ELLNODE *)poldasg); + poldasg = (ASG *)ellNext(&poldasg->node); } asFreeAll(pasbaseold); } @@ -203,7 +201,7 @@ static int myInputFunction(char *buf, int max_size) n = macExpandString(macHandle,mac_input_buffer, my_buffer,BUF_SIZE); if(n<0) { - epicsPrintf("access security: macExpandString failed\n" + errlogPrintf("access security: macExpandString failed\n" "input line: %s\n",mac_input_buffer); return(0); } @@ -243,7 +241,7 @@ long epicsShareAPI asInitFP(FILE *fp,const char *substitutions) macHandle = NULL; } else { macInstallMacros(macHandle,macPairs); - free((void *)macPairs); + free(macPairs); mac_input_buffer = mac_buffer; } } @@ -279,13 +277,13 @@ long epicsShareAPI asRemoveMember(ASMEMBERPVT *asMemberPvt) return(S_asLib_clientsExist); } if(pasgmember->pasg) { - ellDelete(&pasgmember->pasg->memberList,(ELLNODE *)pasgmember); + ellDelete(&pasgmember->pasg->memberList,&pasgmember->node); } else { errMessage(-1,"Logic error in asRemoveMember"); UNLOCK; return(-1); } - free((void *)pasgmember); + free(pasgmember); *asMemberPvt = NULL; UNLOCK; return(0); @@ -301,7 +299,7 @@ long epicsShareAPI asChangeGroup(ASMEMBERPVT *asMemberPvt,const char *newAsgName if(!pasgmember) return(S_asLib_badMember); LOCK; if(pasgmember->pasg) { - ellDelete(&pasgmember->pasg->memberList,(ELLNODE *)pasgmember); + ellDelete(&pasgmember->pasg->memberList,&pasgmember->node); } else { errMessage(-1,"Logic error in asChangeGroup"); UNLOCK; @@ -353,7 +351,7 @@ long epicsShareAPI asAddClient(ASCLIENTPVT *pasClientPvt,ASMEMBERPVT asMemberPvt pasgclient->user = user; pasgclient->host = host; LOCK; - ellAdd(&pasgmember->clientList,(ELLNODE *)pasgclient); + ellAdd(&pasgmember->clientList,&pasgclient->node); status = asComputePvt(pasgclient); UNLOCK; return(status); @@ -395,7 +393,7 @@ long epicsShareAPI asRemoveClient(ASCLIENTPVT *asClientPvt) UNLOCK; return(-1); } - ellDelete(&pasgMember->clientList,(ELLNODE *)pasgclient); + ellDelete(&pasgMember->clientList,&pasgclient->node); UNLOCK; freeListFree(freeListPvt,pasgclient); *asClientPvt = NULL; @@ -508,10 +506,10 @@ int epicsShareAPI asDumpFP( if(puagname) fprintf(fp," {"); else fprintf(fp,"\n"); while(puagname) { fprintf(fp,"%s",puagname->user); - puagname = (UAGNAME *)ellNext((ELLNODE *)puagname); + puagname = (UAGNAME *)ellNext(&puagname->node); if(puagname) fprintf(fp,","); else fprintf(fp,"}\n"); } - puag = (UAG *)ellNext((ELLNODE *)puag); + puag = (UAG *)ellNext(&puag->node); } phag = (HAG *)ellFirst(&pasbase->hagList); if(!phag) fprintf(fp,"No HAGs\n"); @@ -521,10 +519,10 @@ int epicsShareAPI asDumpFP( if(phagname) fprintf(fp," {"); else fprintf(fp,"\n"); while(phagname) { fprintf(fp,"%s",phagname->host); - phagname = (HAGNAME *)ellNext((ELLNODE *)phagname); + phagname = (HAGNAME *)ellNext(&phagname->node); if(phagname) fprintf(fp,","); else fprintf(fp,"}\n"); } - phag = (HAG *)ellNext((ELLNODE *)phag); + phag = (HAG *)ellNext(&phag->node); } pasg = (ASG *)ellFirst(&pasbase->asgList); if(!pasg) fprintf(fp,"No ASGs\n"); @@ -552,7 +550,7 @@ int epicsShareAPI asDumpFP( fprintf(fp," value=%f",pasg->pavalue[pasginp->inpIndex]); } fprintf(fp,"\n"); - pasginp = (ASGINP *)ellNext((ELLNODE *)pasginp); + pasginp = (ASGINP *)ellNext(&pasginp->node); } while(pasgrule) { int print_end_brace; @@ -572,14 +570,14 @@ int epicsShareAPI asDumpFP( if(pasguag) fprintf(fp,"\t\tUAG("); while(pasguag) { fprintf(fp,"%s",pasguag->puag->name); - pasguag = (ASGUAG *)ellNext((ELLNODE *)pasguag); + pasguag = (ASGUAG *)ellNext(&pasguag->node); if(pasguag) fprintf(fp,","); else fprintf(fp,")\n"); } pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList); if(pasghag) fprintf(fp,"\t\tHAG("); while(pasghag) { fprintf(fp,"%s",pasghag->phag->name); - pasghag = (ASGHAG *)ellNext((ELLNODE *)pasghag); + pasghag = (ASGHAG *)ellNext(&pasghag->node); if(pasghag) fprintf(fp,","); else fprintf(fp,")\n"); } if(pasgrule->calc) { @@ -589,7 +587,7 @@ int epicsShareAPI asDumpFP( fprintf(fp,"\n"); } if(print_end_brace) fprintf(fp,"\t}\n"); - pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule); + pasgrule = (ASGRULE *)ellNext(&pasgrule->node); } pasgmember = (ASGMEMBER *)ellFirst(&pasg->memberList); if(!verbose) pasgmember = NULL; @@ -616,12 +614,12 @@ int epicsShareAPI asDumpFP( fprintf(fp," Illegal Access %d",pasgclient->access); if(clientcallback) clientcallback(pasgclient,fp); fprintf(fp,"\n"); - pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient); + pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node); } - pasgmember = (ASGMEMBER *)ellNext((ELLNODE *)pasgmember); + pasgmember = (ASGMEMBER *)ellNext(&pasgmember->node); } if(print_end_brace) fprintf(fp,"}\n"); - pasg = (ASG *)ellNext((ELLNODE *)pasg); + pasg = (ASG *)ellNext(&pasg->node); } return(0); } @@ -641,7 +639,7 @@ int epicsShareAPI asDumpUagFP(FILE *fp,const char *uagname) if(!puag) fprintf(fp,"No UAGs\n"); while(puag) { if(uagname && strcmp(uagname,puag->name)!=0) { - puag = (UAG *)ellNext((ELLNODE *)puag); + puag = (UAG *)ellNext(&puag->node); continue; } fprintf(fp,"UAG(%s)",puag->name); @@ -649,10 +647,10 @@ int epicsShareAPI asDumpUagFP(FILE *fp,const char *uagname) if(puagname) fprintf(fp," {"); else fprintf(fp,"\n"); while(puagname) { fprintf(fp,"%s",puagname->user); - puagname = (UAGNAME *)ellNext((ELLNODE *)puagname); + puagname = (UAGNAME *)ellNext(&puagname->node); if(puagname) fprintf(fp,","); else fprintf(fp,"}\n"); } - puag = (UAG *)ellNext((ELLNODE *)puag); + puag = (UAG *)ellNext(&puag->node); } return(0); } @@ -672,7 +670,7 @@ int epicsShareAPI asDumpHagFP(FILE *fp,const char *hagname) if(!phag) fprintf(fp,"No HAGs\n"); while(phag) { if(hagname && strcmp(hagname,phag->name)!=0) { - phag = (HAG *)ellNext((ELLNODE *)phag); + phag = (HAG *)ellNext(&phag->node); continue; } fprintf(fp,"HAG(%s)",phag->name); @@ -680,10 +678,10 @@ int epicsShareAPI asDumpHagFP(FILE *fp,const char *hagname) if(phagname) fprintf(fp," {"); else fprintf(fp,"\n"); while(phagname) { fprintf(fp,"%s",phagname->host); - phagname = (HAGNAME *)ellNext((ELLNODE *)phagname); + phagname = (HAGNAME *)ellNext(&phagname->node); if(phagname) fprintf(fp,","); else fprintf(fp,"}\n"); } - phag = (HAG *)ellNext((ELLNODE *)phag); + phag = (HAG *)ellNext(&phag->node); } return(0); } @@ -708,7 +706,7 @@ int epicsShareAPI asDumpRulesFP(FILE *fp,const char *asgname) int print_end_brace; if(asgname && strcmp(asgname,pasg->name)!=0) { - pasg = (ASG *)ellNext((ELLNODE *)pasg); + pasg = (ASG *)ellNext(&pasg->node); continue; } fprintf(fp,"ASG(%s)",pasg->name); @@ -728,7 +726,7 @@ int epicsShareAPI asDumpRulesFP(FILE *fp,const char *asgname) fprintf(fp," INVALID"); fprintf(fp," value=%f",pasg->pavalue[pasginp->inpIndex]); fprintf(fp,"\n"); - pasginp = (ASGINP *)ellNext((ELLNODE *)pasginp); + pasginp = (ASGINP *)ellNext(&pasginp->node); } while(pasgrule) { int print_end_brace; @@ -748,14 +746,14 @@ int epicsShareAPI asDumpRulesFP(FILE *fp,const char *asgname) if(pasguag) fprintf(fp,"\t\tUAG("); while(pasguag) { fprintf(fp,"%s",pasguag->puag->name); - pasguag = (ASGUAG *)ellNext((ELLNODE *)pasguag); + pasguag = (ASGUAG *)ellNext(&pasguag->node); if(pasguag) fprintf(fp,","); else fprintf(fp,")\n"); } pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList); if(pasghag) fprintf(fp,"\t\tHAG("); while(pasghag) { fprintf(fp,"%s",pasghag->phag->name); - pasghag = (ASGHAG *)ellNext((ELLNODE *)pasghag); + pasghag = (ASGHAG *)ellNext(&pasghag->node); if(pasghag) fprintf(fp,","); else fprintf(fp,")\n"); } if(pasgrule->calc) { @@ -764,10 +762,10 @@ int epicsShareAPI asDumpRulesFP(FILE *fp,const char *asgname) fprintf(fp,"\n"); } if(print_end_brace) fprintf(fp,"\t}\n"); - pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule); + pasgrule = (ASGRULE *)ellNext(&pasgrule->node); } if(print_end_brace) fprintf(fp,"}\n"); - pasg = (ASG *)ellNext((ELLNODE *)pasg); + pasg = (ASG *)ellNext(&pasg->node); } return(0); } @@ -791,7 +789,7 @@ int epicsShareAPI asDumpMemFP(FILE *fp,const char *asgname, while(pasg) { if(asgname && strcmp(asgname,pasg->name)!=0) { - pasg = (ASG *)ellNext((ELLNODE *)pasg); + pasg = (ASG *)ellNext(&pasg->node); continue; } fprintf(fp,"ASG(%s)\n",pasg->name); @@ -820,11 +818,11 @@ int epicsShareAPI asDumpMemFP(FILE *fp,const char *asgname, else fprintf(fp," Illegal Access %d",pasgclient->access); fprintf(fp,"\n"); - pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient); + pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node); } - pasgmember = (ASGMEMBER *)ellNext((ELLNODE *)pasgmember); + pasgmember = (ASGMEMBER *)ellNext(&pasgmember->node); } - pasg = (ASG *)ellNext((ELLNODE *)pasg); + pasg = (ASG *)ellNext(&pasg->node); } return(0); } @@ -875,23 +873,23 @@ static long asAddMemberPvt(ASMEMBERPVT *pasMemberPvt,const char *asgName) pgroup = (ASG *)ellFirst(&pasbase->asgList); while(pgroup) { if(strcmp(pgroup->name,pasgmember->asgName)==0) goto got_it; - pgroup = (ASG *)ellNext((ELLNODE *)pgroup); + pgroup = (ASG *)ellNext(&pgroup->node); } /* Put it in DEFAULT*/ pgroup = (ASG *)ellFirst(&pasbase->asgList); while(pgroup) { if(strcmp(pgroup->name,DEFAULT)==0) goto got_it; - pgroup = (ASG *)ellNext((ELLNODE *)pgroup); + pgroup = (ASG *)ellNext(&pgroup->node); } errMessage(-1,"Logic Error in asAddMember"); return(-1); got_it: pasgmember->pasg = pgroup; - ellAdd(&pgroup->memberList,(ELLNODE *)pasgmember); + ellAdd(&pgroup->memberList,&pasgmember->node); pasgclient = (ASGCLIENT *)ellFirst(&pasgmember->clientList); while(pasgclient) { asComputePvt((ASCLIENTPVT)pasgclient); - pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient); + pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node); } return(0); } @@ -904,7 +902,7 @@ static long asComputeAllAsgPvt(void) pasg = (ASG *)ellFirst(&pasbase->asgList); while(pasg) { asComputeAsgPvt(pasg); - pasg = (ASG *)ellNext((ELLNODE *)pasg); + pasg = (ASG *)ellNext(&pasg->node); } return(0); } @@ -930,7 +928,7 @@ static long asComputeAsgPvt(ASG *pasg) pasgrule->result = ((result>.99) && (result<1.01)) ? 1 : 0; } } - pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule); + pasgrule = (ASGRULE *)ellNext(&pasgrule->node); } pasg->inpChanged = FALSE; pasgmember = (ASGMEMBER *)ellFirst(&pasg->memberList); @@ -938,9 +936,9 @@ static long asComputeAsgPvt(ASG *pasg) pasgclient = (ASGCLIENT *)ellFirst(&pasgmember->clientList); while(pasgclient) { asComputePvt((ASCLIENTPVT)pasgclient); - pasgclient = (ASGCLIENT *)ellNext((ELLNODE *)pasgclient); + pasgclient = (ASGCLIENT *)ellNext(&pasgclient->node); } - pasgmember = (ASGMEMBER *)ellNext((ELLNODE *)pasgmember); + pasgmember = (ASGMEMBER *)ellNext(&pasgmember->node); } return(0); } @@ -979,7 +977,7 @@ static long asComputePvt(ASCLIENTPVT asClientPvt) pgphentry = gphFind(pasbase->phash,pasgclient->user,puag); if(pgphentry) goto check_hag; } - pasguag = (ASGUAG *)ellNext((ELLNODE *)pasguag); + pasguag = (ASGUAG *)ellNext(&pasguag->node); } goto next_rule; } @@ -995,7 +993,7 @@ check_hag: pgphentry=gphFind(pasbase->phash,pasgclient->host,phag); if(pgphentry) goto check_calc; } - pasghag = (ASGHAG *)ellNext((ELLNODE *)pasghag); + pasghag = (ASGHAG *)ellNext(&pasghag->node); } goto next_rule; } @@ -1006,7 +1004,7 @@ check_calc: trapMask = pasgrule->trapMask; } next_rule: - pasgrule = (ASGRULE *)ellNext((ELLNODE *)pasgrule); + pasgrule = (ASGRULE *)ellNext(&pasgrule->node); } pasgclient->access = access; pasgclient->trapMask = trapMask; @@ -1033,70 +1031,70 @@ static void asFreeAll(ASBASE *pasbase) while(puag) { puagname = (UAGNAME *)ellFirst(&puag->list); while(puagname) { - pnext = ellNext((ELLNODE *)puagname); - ellDelete(&puag->list,(ELLNODE *)puagname); - free((void *)puagname); + pnext = ellNext(&puagname->node); + ellDelete(&puag->list,&puagname->node); + free(puagname); puagname = pnext; } - pnext = ellNext((ELLNODE *)puag); - ellDelete(&pasbase->uagList,(ELLNODE *)puag); - free((void *)puag); + pnext = ellNext(&puag->node); + ellDelete(&pasbase->uagList,&puag->node); + free(puag); puag = pnext; } phag = (HAG *)ellFirst(&pasbase->hagList); while(phag) { phagname = (HAGNAME *)ellFirst(&phag->list); while(phagname) { - pnext = ellNext((ELLNODE *)phagname); - ellDelete(&phag->list,(ELLNODE *)phagname); - free((void *)phagname); + pnext = ellNext(&phagname->node); + ellDelete(&phag->list,&phagname->node); + free(phagname); phagname = pnext; } - pnext = ellNext((ELLNODE *)phag); - ellDelete(&pasbase->hagList,(ELLNODE *)phag); - free((void *)phag); + pnext = ellNext(&phag->node); + ellDelete(&pasbase->hagList,&phag->node); + free(phag); phag = pnext; } pasg = (ASG *)ellFirst(&pasbase->asgList); while(pasg) { - free((void *)pasg->pavalue); + free(pasg->pavalue); pasginp = (ASGINP *)ellFirst(&pasg->inpList); while(pasginp) { - pnext = ellNext((ELLNODE *)pasginp); - ellDelete(&pasg->inpList,(ELLNODE *)pasginp); - free((void *)pasginp); + pnext = ellNext(&pasginp->node); + ellDelete(&pasg->inpList,&pasginp->node); + free(pasginp); pasginp = pnext; } pasgrule = (ASGRULE *)ellFirst(&pasg->ruleList); while(pasgrule) { - free((void *)pasgrule->calc); - free((void *)pasgrule->rpcl); + free(pasgrule->calc); + free(pasgrule->rpcl); pasguag = (ASGUAG *)ellFirst(&pasgrule->uagList); while(pasguag) { - pnext = ellNext((ELLNODE *)pasguag); - ellDelete(&pasgrule->uagList,(ELLNODE *)pasguag); - free((void *)pasguag); + pnext = ellNext(&pasguag->node); + ellDelete(&pasgrule->uagList,&pasguag->node); + free(pasguag); pasguag = pnext; } pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList); while(pasghag) { - pnext = ellNext((ELLNODE *)pasghag); - ellDelete(&pasgrule->hagList,(ELLNODE *)pasghag); - free((void *)pasghag); + pnext = ellNext(&pasghag->node); + ellDelete(&pasgrule->hagList,&pasghag->node); + free(pasghag); pasghag = pnext; } - pnext = ellNext((ELLNODE *)pasgrule); - ellDelete(&pasg->ruleList,(ELLNODE *)pasgrule); - free((void *)pasgrule); + pnext = ellNext(&pasgrule->node); + ellDelete(&pasg->ruleList,&pasgrule->node); + free(pasgrule); pasgrule = pnext; } - pnext = ellNext((ELLNODE *)pasg); - ellDelete(&pasbase->asgList,(ELLNODE *)pasg); - free((void *)pasg); + pnext = ellNext(&pasg->node); + ellDelete(&pasbase->asgList,&pasg->node); + free(pasg); pasg = pnext; } gphFreeMem(pasbase->phash); - free((void *)pasbase); + free(pasbase); } /*Beginning of routines called by lex code*/ @@ -1117,17 +1115,17 @@ static UAG *asUagAdd(const char *uagName) errlogPrintf("Duplicate User Access Group named '%s'\n", uagName); return(NULL); } - pnext = (UAG *)ellNext((ELLNODE *)pnext); + pnext = (UAG *)ellNext(&pnext->node); } puag = asCalloc(1,sizeof(UAG)+strlen(uagName)+1); ellInit(&puag->list); puag->name = (char *)(puag+1); strcpy(puag->name,uagName); if(pnext==NULL) { /*Add to end of list*/ - ellAdd(&pasbase->uagList,(ELLNODE *)puag); + ellAdd(&pasbase->uagList,&puag->node); } else { - pprev = (UAG *)ellPrevious((ELLNODE *)pnext); - ellInsert(&pasbase->uagList,(ELLNODE *)pprev,(ELLNODE *)puag); + pprev = (UAG *)ellPrevious(&pnext->node); + ellInsert(&pasbase->uagList,&pprev->node,&puag->node); } return(puag); } @@ -1140,7 +1138,7 @@ static long asUagAddUser(UAG *puag,const char *user) puagname = asCalloc(1,sizeof(UAGNAME)+strlen(user)+1); puagname->user = (char *)(puagname+1); strcpy(puagname->user,user); - ellAdd(&puag->list,(ELLNODE *)puagname); + ellAdd(&puag->list,&puagname->node); return(0); } @@ -1161,17 +1159,17 @@ static HAG *asHagAdd(const char *hagName) errlogPrintf("Duplicate Host Access Group named '%s'\n", hagName); return(NULL); } - pnext = (HAG *)ellNext((ELLNODE *)pnext); + pnext = (HAG *)ellNext(&pnext->node); } phag = asCalloc(1,sizeof(HAG)+strlen(hagName)+1); ellInit(&phag->list); phag->name = (char *)(phag+1); strcpy(phag->name,hagName); if(pnext==NULL) { /*Add to end of list*/ - ellAdd(&pasbase->hagList,(ELLNODE *)phag); + ellAdd(&pasbase->hagList,&phag->node); } else { - pprev = (HAG *)ellPrevious((ELLNODE *)pnext); - ellInsert(&pasbase->hagList,(ELLNODE *)pprev,(ELLNODE *)phag); + pprev = (HAG *)ellPrevious(&pnext->node); + ellInsert(&pasbase->hagList,&pprev->node,&phag->node); } return(phag); } @@ -1188,7 +1186,7 @@ static long asHagAddHost(HAG *phag,const char *host) for (i = 0; i < len; i++) { phagname->host[i] = (char)tolower((int)host[i]); } - ellAdd(&phag->list, (ELLNODE *)phagname); + ellAdd(&phag->list, &phagname->node); return 0; } @@ -1214,7 +1212,7 @@ static ASG *asAsgAdd(const char *asgName) errlogPrintf("Duplicate Access Security Group named '%s'\n", asgName); return(NULL); } - pnext = (ASG *)ellNext((ELLNODE *)pnext); + pnext = (ASG *)ellNext(&pnext->node); } pasg = asCalloc(1,sizeof(ASG)+strlen(asgName)+1); ellInit(&pasg->inpList); @@ -1223,10 +1221,10 @@ static ASG *asAsgAdd(const char *asgName) pasg->name = (char *)(pasg+1); strcpy(pasg->name,asgName); if(pnext==NULL) { /*Add to end of list*/ - ellAdd(&pasbase->asgList,(ELLNODE *)pasg); + ellAdd(&pasbase->asgList,&pasg->node); } else { - pprev = (ASG *)ellPrevious((ELLNODE *)pnext); - ellInsert(&pasbase->asgList,(ELLNODE *)pprev,(ELLNODE *)pasg); + pprev = (ASG *)ellPrevious(&pnext->node); + ellInsert(&pasbase->asgList,&pprev->node,&pasg->node); } return(pasg); } @@ -1241,7 +1239,7 @@ static long asAsgAddInp(ASG *pasg,const char *inp,int inpIndex) strcpy(pasginp->inp,inp); pasginp->pasg = pasg; pasginp->inpIndex = inpIndex; - ellAdd(&pasg->inpList,(ELLNODE *)pasginp); + ellAdd(&pasg->inpList,&pasginp->node); return(0); } @@ -1256,7 +1254,7 @@ static ASGRULE *asAsgAddRule(ASG *pasg,asAccessRights access,int level) pasgrule->level = level; ellInit(&pasgrule->uagList); ellInit(&pasgrule->hagList); - ellAdd(&pasg->ruleList,(ELLNODE *)pasgrule); + ellAdd(&pasg->ruleList,&pasgrule->node); return(pasgrule); } @@ -1267,52 +1265,56 @@ static long asAsgAddRuleOptions(ASGRULE *pasgrule,int trapMask) return(0); } -static long asAsgRuleUagAdd(ASGRULE *pasgrule,const char *name) +static long asAsgRuleUagAdd(ASGRULE *pasgrule, const char *name) { ASGUAG *pasguag; UAG *puag; ASBASE *pasbase = (ASBASE *)pasbasenew; - long status; - if(!pasgrule) return(0); + if (!pasgrule) + return 0; + puag = (UAG *)ellFirst(&pasbase->uagList); - while(puag) { - if(strcmp(puag->name,name)==0) break; - puag = (UAG *)ellNext((ELLNODE *)puag); + while (puag) { + if (strcmp(puag->name, name)==0) + break; + puag = (UAG *)ellNext(&puag->node); } - if(!puag){ - status = S_asLib_noUag; - errlogPrintf("No User Access Group named '%s' defined\n", name); - return(S_asLib_noUag); + if (!puag){ + errlogPrintf("No User Access Group named '%s' defined\n", name); + return S_asLib_noUag; } - pasguag = asCalloc(1,sizeof(ASGUAG)); + + pasguag = asCalloc(1, sizeof(ASGUAG)); pasguag->puag = puag; - ellAdd(&pasgrule->uagList,(ELLNODE *)pasguag); - return(0); + ellAdd(&pasgrule->uagList, &pasguag->node); + return 0; } -static long asAsgRuleHagAdd(ASGRULE *pasgrule,const char *name) +static long asAsgRuleHagAdd(ASGRULE *pasgrule, const char *name) { ASGHAG *pasghag; HAG *phag; ASBASE *pasbase = (ASBASE *)pasbasenew; - long status; - if(!pasgrule) return(0); + if (!pasgrule) + return 0; + phag = (HAG *)ellFirst(&pasbase->hagList); - while(phag) { - if(strcmp(phag->name,name)==0) break; - phag = (HAG *)ellNext((ELLNODE *)phag); + while (phag) { + if (strcmp(phag->name, name)==0) + break; + phag = (HAG *)ellNext(&phag->node); } - if(!phag){ - status = S_asLib_noHag; - errlogPrintf("No Host Access Group named '%s' defined\n", name); - return(S_asLib_noHag); + if (!phag){ + errlogPrintf("No Host Access Group named '%s' defined\n", name); + return S_asLib_noHag; } - pasghag = asCalloc(1,sizeof(ASGHAG)); + + pasghag = asCalloc(1, sizeof(ASGHAG)); pasghag->phag = phag; - ellAdd(&pasgrule->hagList,(ELLNODE *)pasghag); - return(0); + ellAdd(&pasgrule->hagList, &pasghag->node); + return 0; } static long asAsgRuleCalc(ASGRULE *pasgrule,const char *calc) @@ -1329,8 +1331,8 @@ static long asAsgRuleCalc(ASGRULE *pasgrule,const char *calc) pasgrule->rpcl = asCalloc(1, INFIX_TO_POSTFIX_SIZE(insize)); status = postfix(pasgrule->calc, pasgrule->rpcl, &err); if(status) { - free((void *)pasgrule->calc); - free((void *)pasgrule->rpcl); + free(pasgrule->calc); + free(pasgrule->rpcl); pasgrule->calc = NULL; pasgrule->rpcl = NULL; status = S_asLib_badCalc; @@ -1340,8 +1342,8 @@ static long asAsgRuleCalc(ASGRULE *pasgrule,const char *calc) calcArgUsage(pasgrule->rpcl, &pasgrule->inpUsed, &stores); /* Until someone proves stores are not dangerous, don't allow them */ if (stores) { - free((void *)pasgrule->calc); - free((void *)pasgrule->rpcl); + free(pasgrule->calc); + free(pasgrule->rpcl); pasgrule->calc = NULL; pasgrule->rpcl = NULL; status = S_asLib_badCalc;