diff --git a/src/libCom/misc/epicsExit.c b/src/libCom/misc/epicsExit.c index 6ae9dffd5..0fbed224b 100644 --- a/src/libCom/misc/epicsExit.c +++ b/src/libCom/misc/epicsExit.c @@ -71,14 +71,18 @@ static void exitPvtOnceFunc(void *pParm) { exitPvtPerThread = epicsThreadPrivateCreate (); assert ( exitPvtPerThread ); - pExitPvtPerProcess = createExitPvt (); - assert ( pExitPvtPerProcess ); exitPvtLock = epicsMutexMustCreate (); } +static void epicsExitInit(void) +{ + epicsThreadOnce ( & exitPvtOnce, exitPvtOnceFunc, 0 ); +} + static void epicsExitCallAtExitsPvt(exitPvt *pep) { exitNode *pexitNode; + while ( ( pexitNode = (exitNode *) ellLast ( & pep->list ) ) ) { if (atExitDebug && pexitNode->name[0]) fprintf(stderr, "atExit %s(%p)\n", pexitNode->name, pexitNode->arg); @@ -93,7 +97,8 @@ static void epicsExitCallAtExitsPvt(exitPvt *pep) epicsShareFunc void epicsExitCallAtExits(void) { exitPvt * pep = 0; - epicsThreadOnce ( & exitPvtOnce, exitPvtOnceFunc, 0 ); + + epicsExitInit (); epicsMutexMustLock ( exitPvtLock ); if ( pExitPvtPerProcess ) { pep = pExitPvtPerProcess; @@ -109,7 +114,8 @@ epicsShareFunc void epicsExitCallAtExits(void) epicsShareFunc void epicsExitCallAtThreadExits(void) { exitPvt * pep; - epicsThreadOnce ( & exitPvtOnce, exitPvtOnceFunc, 0 ); + + epicsExitInit (); pep = epicsThreadPrivateGet ( exitPvtPerThread ); if ( pep ) { epicsExitCallAtExitsPvt ( pep ); @@ -122,7 +128,7 @@ static int epicsAtExitPvt(exitPvt *pep, epicsExitFunc func, void *arg, const cha { int status = -1; exitNode * pExitNode = calloc ( 1, sizeof( *pExitNode ) + (name?strlen(name):0) ); - = calloc ( 1, sizeof( *pExitNode ) ); + if ( pExitNode ) { pExitNode->func = func; pExitNode->arg = arg; @@ -137,7 +143,8 @@ static int epicsAtExitPvt(exitPvt *pep, epicsExitFunc func, void *arg, const cha epicsShareFunc int epicsAtThreadExit(epicsExitFunc func, void *arg) { exitPvt * pep; - epicsThreadOnce ( & exitPvtOnce, exitPvtOnceFunc, 0 ); + + epicsExitInit (); pep = epicsThreadPrivateGet ( exitPvtPerThread ); if ( ! pep ) { pep = createExitPvt (); @@ -152,8 +159,12 @@ epicsShareFunc int epicsAtThreadExit(epicsExitFunc func, void *arg) epicsShareFunc int epicsAtExit3(epicsExitFunc func, void *arg, const char* name) { int status = -1; - epicsThreadOnce ( & exitPvtOnce, exitPvtOnceFunc, 0 ); + + epicsExitInit (); epicsMutexMustLock ( exitPvtLock ); + if ( !pExitPvtPerProcess ) { + pExitPvtPerProcess = createExitPvt (); + } if ( pExitPvtPerProcess ) { status = epicsAtExitPvt ( pExitPvtPerProcess, func, arg, name ); } @@ -164,7 +175,7 @@ epicsShareFunc int epicsAtExit3(epicsExitFunc func, void *arg, const char* name) epicsShareFunc void epicsExit(int status) { epicsExitCallAtExits(); - epicsThreadSleep(1.0); + epicsThreadSleep(0.1); exit(status); } diff --git a/src/libCom/test/epicsExitTest.c b/src/libCom/test/epicsExitTest.c index f464b707c..dc901b5ac 100644 --- a/src/libCom/test/epicsExitTest.c +++ b/src/libCom/test/epicsExitTest.c @@ -59,12 +59,20 @@ static void thread(void *arg) testDiag("%s starting", pinfo->name); pinfo->terminate = epicsEventMustCreate(epicsEventEmpty); pinfo->terminated = epicsEventMustCreate(epicsEventEmpty); - epicsAtExit(atExit, pinfo); - epicsAtThreadExit(atThreadExit, pinfo); + testOk(!epicsAtExit(atExit, pinfo), "Registered atExit(%p)", pinfo); + testOk(!epicsAtThreadExit(atThreadExit, pinfo), + "Registered atThreadExit(%p)", pinfo); testDiag("%s waiting for atExit", pinfo->name); epicsEventMustWait(pinfo->terminate); } +int count; + +static void counter(void *pvt) +{ + count++; +} + static void mainExit(void *pvt) { testPass("Reached mainExit"); @@ -77,16 +85,23 @@ MAIN(epicsExitTest) info *pinfoA = (info *)calloc(1, sizeof(info)); info *pinfoB = (info *)calloc(1, sizeof(info)); - testPlan(7); + testPlan(15); - epicsAtExit(mainExit, NULL); + testOk(!epicsAtExit(counter, NULL), "Registered counter()"); + count = 0; + epicsExitCallAtExits(); + testOk(count == 1, "counter() called once"); + epicsExitCallAtExits(); + testOk(count == 1, "unregistered counter() not called"); + + testOk(!epicsAtExit(mainExit, NULL), "Registered mainExit()"); epicsThreadCreate("threadA", 50, stackSize, thread, pinfoA); epicsThreadSleep(0.1); epicsThreadCreate("threadB", 50, stackSize, thread, pinfoB); epicsThreadSleep(1.0); - testDiag("Calling epicsExit\n"); + testDiag("Calling epicsExit"); epicsExit(0); return 0; }