diff --git a/acsMotionApp/src/SPiiPlusAuxDriver.cpp b/acsMotionApp/src/SPiiPlusAuxDriver.cpp index 0a61e88..3c0c753 100644 --- a/acsMotionApp/src/SPiiPlusAuxDriver.cpp +++ b/acsMotionApp/src/SPiiPlusAuxDriver.cpp @@ -4,6 +4,7 @@ #include #include +#include // asynMotorController.h includes asynPortDriver.h #include @@ -23,6 +24,14 @@ static void SPiiPlusAuxIOThreadC(void *pPvt) pAux->pollerThread(); } +static void shutdownCallback(void *pPvt) +{ + SPiiPlusController *pC = static_cast(pPvt); + + pC->lock(); + pC->shuttingDown_ = 1; + pC->unlock(); +} SPiiPlusAuxIO::SPiiPlusAuxIO(const char *ACSAuxPortName, const char* asynPortName, int numChannels, double pollPeriod) : asynPortDriver(ACSAuxPortName, numChannels, @@ -42,6 +51,9 @@ SPiiPlusAuxIO::SPiiPlusAuxIO(const char *ACSAuxPortName, const char* asynPortNam pComm_ = new SPiiPlusComm(ACSCommPortName, asynPortName, numChannels); + /* Set an EPICS exit handler that will shut down polling before asyn kills the IP sockets */ + epicsAtExit(shutdownCallback, pC_); + /* * MP4U controllers have significantly larger arrays for the AIN, AOUT, IN and OUT commands than the controller * has I/O channels. Assume the user will specify a numChannels that is appropriate for their controller. @@ -195,6 +207,12 @@ void SPiiPlusAuxIO::pollerThread() while(1) { lock(); + // Stop the thread if the IOC is shutting down + if (shuttingDown_) { + unlock(); + break; + } + // assume status is good status = asynSuccess; diff --git a/acsMotionApp/src/SPiiPlusAuxDriver.h b/acsMotionApp/src/SPiiPlusAuxDriver.h index 039ea13..8cd7334 100644 --- a/acsMotionApp/src/SPiiPlusAuxDriver.h +++ b/acsMotionApp/src/SPiiPlusAuxDriver.h @@ -35,6 +35,8 @@ class epicsShareClass SPiiPlusAuxIO : public asynPortDriver { /* These are methods unique to SPiiPlusAuxIO */ asynStatus writeBits(epicsUInt32 chan, epicsUInt32 mask, epicsUInt32 value); asynStatus writeAnalog(epicsUInt32 chan, epicsFloat64 value); + + int shuttingDown_; /**< Flag indicating that IOC is shutting down. Stops poller */ protected: SPiiPlusComm *pComm_; diff --git a/acsMotionApp/src/SPiiPlusDriver.cpp b/acsMotionApp/src/SPiiPlusDriver.cpp index 7363bde..5db7d2e 100644 --- a/acsMotionApp/src/SPiiPlusDriver.cpp +++ b/acsMotionApp/src/SPiiPlusDriver.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -34,6 +35,15 @@ static void SPiiPlusProfileThreadC(void *pPvt); #define MIN(a,b) ((a)<(b)? (a): (b)) #endif +static void shutdownCallback(void *pPvt) +{ + SPiiPlusController *pC = static_cast(pPvt); + + pC->lock(); + pC->shuttingDown_ = 1; + pC->unlock(); +} + SPiiPlusController::SPiiPlusController(const char* ACSPortName, const char* asynPortName, int numAxes, double movingPollPeriod, double idlePollPeriod, const char* virtualAxisList) @@ -56,6 +66,9 @@ SPiiPlusController::SPiiPlusController(const char* ACSPortName, const char* asyn std::stringstream cmd; static const char *functionName="SPiiPlusController"; + /* Set an EPICS exit handler that will shut down polling before asyn kills the IP sockets */ + epicsAtExit(shutdownCallback, this); + // Create parameters createParam(SPiiPlusHomingMethodString, asynParamInt32, &SPiiPlusHomingMethod_); createParam(SPiiPlusMaxVelocityString, asynParamFloat64, &SPiiPlusMaxVelocity_); @@ -1805,9 +1818,27 @@ static void SPiiPlusProfileThreadC(void *pPvt) /* Function which runs in its own thread to execute profiles */ void SPiiPlusController::profileThread() { + double timeout; + int status; + + /* Is the idle poll period frequent enough to stop the profileMove thread before the IOC stops? */ + timeout = movingPollPeriod_; + while (true) { - epicsEventWait(profileExecuteEvent_); - runProfile(); + /* Exit the thread if the IOC is shutting down */ + lock(); + if (shuttingDown_) { + unlock(); + break; + } else { + unlock(); + } + + status = epicsEventWaitWithTimeout(profileExecuteEvent_, timeout); + if (status == epicsEventWaitOK) { + /* We got an event, rather than a timeout */ + runProfile(); + } } } diff --git a/acsMotionApp/src/SPiiPlusDriver.h b/acsMotionApp/src/SPiiPlusDriver.h index 823b8b0..c552e03 100644 --- a/acsMotionApp/src/SPiiPlusDriver.h +++ b/acsMotionApp/src/SPiiPlusDriver.h @@ -98,7 +98,7 @@ -// drvInfo strings for extra parameters that the XPS controller supports +// drvInfo strings for extra parameters that the ACS controller supports #define SPiiPlusHomingMethodString "SPIIPLUS_HOMING_METHOD" #define SPiiPlusMaxVelocityString "SPIIPLUS_MAX_VELOCITY" #define SPiiPlusMaxAccelerationString "SPIIPLUS_MAX_ACCELERATION"