Files
pcas/src/libCom/misc/epicsExit.c
T
Jeff Hill 3d377eed1d removed atexit handler that calls epicsThreadExit because:
o recursive exit call is bad
o this causes shutdown problems with DLL codes on windows
=> the workaround is an atexit handler that calls epicsExitCallAtExits in
the poosix osdThreads atexit handler
2004-09-16 18:22:33 +00:00

93 lines
2.7 KiB
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.
\*************************************************************************/
/*epicsExit.c*/
/* Author: Marty Kraimer */
/* Date: 23AUG2004 */
#include <stdlib.h>
#include <errno.h>
#define epicsExportSharedSymbols
#include "ellLib.h"
#include "epicsThread.h"
#include "epicsMutex.h"
#include "cantProceed.h"
#include "epicsExit.h"
typedef void (*epicsExitFunc)(void *arg);
typedef struct exitNode {
ELLNODE node;
epicsExitFunc func;
void *arg;
}exitNode;
typedef struct exitPvt {
ELLLIST list;
epicsMutexId lock;
int epicsExitNcalls;
}exitPvt;
static exitPvt exitPvtInstance;
static exitPvt *pexitPvt = &exitPvtInstance;
static epicsThreadOnceId createOnce = EPICS_THREAD_ONCE_INIT;
static void createExitPvt(void)
{
pexitPvt->lock = epicsMutexMustCreate();
ellInit(&pexitPvt->list);
}
epicsShareFunc void epicsShareAPI epicsExitCallAtExits(void)
{
exitNode *pexitNode;
epicsThreadOnce(&createOnce,(EPICSTHREADFUNC)createExitPvt,0);
epicsMutexMustLock(pexitPvt->lock);
if(pexitPvt->epicsExitNcalls++>0) {
epicsMutexUnlock(pexitPvt->lock);
return;
}
epicsMutexUnlock(pexitPvt->lock);
/* remove exitNodes in reverse order that they were added*/
while((pexitNode = (exitNode *)ellLast(&pexitPvt->list))) {
ellDelete(&pexitPvt->list,&pexitNode->node);
pexitNode->func(pexitNode->arg);
free(pexitNode);
}
/* epicsMutexDestroy is not called because of possible race conditions*/
/*epicsMutexDestroy(pexitPvt->lock);*/
}
epicsShareFunc void epicsShareAPI epicsExit(int status)
{
epicsExitCallAtExits();
epicsThreadSleep(1.0);
exit(status);
}
epicsShareFunc int epicsShareAPI epicsAtExit(epicsExitFunc func, void *arg)
{
exitNode *pexitNode;
epicsThreadOnce(&createOnce,(EPICSTHREADFUNC)createExitPvt,0);
pexitNode = callocMustSucceed(1,sizeof(exitNode),"epicsAtExit");
pexitNode->func = func;
pexitNode->arg = arg;
epicsMutexMustLock(pexitPvt->lock);
if(pexitPvt->epicsExitNcalls>0) {
epicsMutexUnlock(pexitPvt->lock);
free(pexitNode);
return -1;
}
ellAdd(&pexitPvt->list,&pexitNode->node);
epicsMutexUnlock(pexitPvt->lock);
return 0;
}