/*************************************************************************\ * Copyright (c) 2006 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * SPDX-License-Identifier: EPICS * EPICS BASE is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* epicsExitTest.cpp */ /* Author: Marty Kraimer Date: 09JUL2004*/ #include #include #include #include #include #include #include "epicsThread.h" #include "epicsAssert.h" #include "epicsEvent.h" #include "epicsExit.h" #include "epicsUnitTest.h" #include "testMain.h" typedef struct info { char name[64]; epicsEventId terminate; epicsEventId terminated; }info; static void atExit(void *pvt) { info *pinfo = (info *)pvt; testPass("%s reached atExit", pinfo->name); epicsEventSignal(pinfo->terminate); /*Now wait for thread to terminate*/ epicsEventMustWait(pinfo->terminated); testPass("%s destroying pinfo", pinfo->name); epicsEventDestroy(pinfo->terminate); epicsEventDestroy(pinfo->terminated); free(pinfo); } static void atThreadExit(void *pvt) { info *pinfo = (info *)pvt; testPass("%s terminating", pinfo->name); epicsEventSignal(pinfo->terminated); } static void thread(void *arg) { info *pinfo = (info *)arg; strcpy(pinfo->name, epicsThreadGetNameSelf()); testDiag("%s starting", pinfo->name); pinfo->terminate = epicsEventMustCreate(epicsEventEmpty); pinfo->terminated = epicsEventMustCreate(epicsEventEmpty); 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"); testDone(); } MAIN(epicsExitTest) { unsigned int stackSize = epicsThreadGetStackSize(epicsThreadStackSmall); info *pinfoA = (info *)calloc(1, sizeof(info)); info *pinfoB = (info *)calloc(1, sizeof(info)); testPlan(15); 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"); epicsExit(0); return 0; }