From dd5406249694408fd355dc7456ff4c1ba6f9f903 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Fri, 13 Mar 2009 17:23:07 +0000 Subject: [PATCH] fixed mantis 336 - timer queue should have try / catch block around call to user's expiration callback --- src/libCom/timer/timerPrivate.h | 8 ++++++ src/libCom/timer/timerQueue.cpp | 46 ++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/libCom/timer/timerPrivate.h b/src/libCom/timer/timerPrivate.h index cd6689ca3..6760d1bf2 100644 --- a/src/libCom/timer/timerPrivate.h +++ b/src/libCom/timer/timerPrivate.h @@ -18,6 +18,8 @@ #ifndef epicsTimerPrivate_h #define epicsTimerPrivate_h +#include + #include "tsFreeList.h" #include "epicsSingleton.h" #include "tsDLList.h" @@ -86,6 +88,8 @@ private: friend class timerQueue; }; +using std :: type_info; + class timerQueue : public epicsTimerQueue { public: timerQueue ( epicsTimerQueueNotify ¬ify ); @@ -103,7 +107,11 @@ private: epicsTimerQueueNotify & notify; timer * pExpireTmr; epicsThreadId processThread; + epicsTime exceptMsgTimeStamp; bool cancelPending; + static const double exceptMsgMinPeriod; + void printExceptMsg ( const char * pName, + const type_info & type ); timerQueue ( const timerQueue & ); timerQueue & operator = ( const timerQueue & ); friend class timer; diff --git a/src/libCom/timer/timerQueue.cpp b/src/libCom/timer/timerQueue.cpp index 911faf4b0..548300307 100644 --- a/src/libCom/timer/timerQueue.cpp +++ b/src/libCom/timer/timerQueue.cpp @@ -19,12 +19,19 @@ #define epicsExportSharedSymbols #include "epicsGuard.h" #include "timerPrivate.h" +#include "errlog.h" + +const double timerQueue :: exceptMsgMinPeriod = 60.0 * 5.0; // seconds epicsTimerQueue::~epicsTimerQueue () {} timerQueue::timerQueue ( epicsTimerQueueNotify & notifyIn ) : - notify ( notifyIn ), pExpireTmr ( 0 ), - processThread ( 0 ), cancelPending ( false ) + notify ( notifyIn ), + pExpireTmr ( 0 ), + processThread ( 0 ), + exceptMsgTimeStamp ( + epicsTime :: getCurrent () - exceptMsgMinPeriod ), + cancelPending ( false ) { } @@ -36,6 +43,30 @@ timerQueue::~timerQueue () } } +void timerQueue :: + printExceptMsg ( const char * pName, const type_info & type ) +{ + epicsTime cur = epicsTime :: getCurrent (); + double delay = cur - this->exceptMsgTimeStamp; + if ( delay >= exceptMsgMinPeriod ) { + this->exceptMsgTimeStamp = cur; + char date[64]; + cur.strftime ( date, sizeof ( date ), + "%a %b %d %Y %H:%M:%S.%f" ); + // we dont touch the typeid for the timer expiration + // notify interface here because they might have + // destroyed the timer during its callback + errlogPrintf ( + "timerQueue: Unexpected C++ exception \"%s\" " + "with type \"%s\" during timer expiration " + "callback at %s\n", + pName, + type.name (), + date ); + errlogFlush (); + } +} + double timerQueue::process ( const epicsTime & currentTime ) { epicsGuard < epicsMutex > guard ( this->mutex ); @@ -96,8 +127,15 @@ double timerQueue::process ( const epicsTime & currentTime ) debugPrintf ( ( "%5u expired \"%s\" with error %f sec\n", N++, typeid ( this->pExpireTmr->notify ).name (), currentTime - this->pExpireTmr->exp ) ); - - expStat = pTmpNotify->expire ( currentTime ); + try { + expStat = pTmpNotify->expire ( currentTime ); + } + catch ( std::exception & except ) { + printExceptMsg ( except.what (), typeid ( except ) ); + } + catch ( ... ) { + printExceptMsg ( "non-standard exception", typeid ( void ) ); + } } //