Make epicsExit subsystem reusable.
Calling epicsAtExit() after epicsExitCallAtExits() now recreates the per-process list and registers the routine.
This commit is contained in:
committed by
Michael Davidsaver
parent
80dd66a58d
commit
60a0c7f181
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user