00001 00033 #include "llviewerprecompiledheaders.h" 00034 #include "llwatchdog.h" 00035 00036 // This class runs the watchdog timing thread. 00037 class LLWatchdogTimerThread : public LLThread 00038 { 00039 public: 00040 LLWatchdogTimerThread() : 00041 LLThread("Watchdog"), 00042 mSleepMsecs(0), 00043 mStopping(false) 00044 { 00045 } 00046 00047 ~LLWatchdogTimerThread() {} 00048 00049 void setSleepTime(long ms) { mSleepMsecs = ms; } 00050 void stop() 00051 { 00052 mStopping = true; 00053 ms_sleep(1); 00054 } 00055 00056 /* virtual */ void run() 00057 { 00058 while(!mStopping) 00059 { 00060 LLWatchdog::getInstance()->run(); 00061 ms_sleep(mSleepMsecs); 00062 } 00063 } 00064 00065 private: 00066 long mSleepMsecs; 00067 bool mStopping; 00068 }; 00069 00070 // LLWatchdogEntry 00071 LLWatchdogEntry::LLWatchdogEntry() 00072 { 00073 } 00074 00075 LLWatchdogEntry::~LLWatchdogEntry() 00076 { 00077 } 00078 00079 void LLWatchdogEntry::start() 00080 { 00081 LLWatchdog::getInstance()->add(this); 00082 } 00083 00084 void LLWatchdogEntry::stop() 00085 { 00086 LLWatchdog::getInstance()->remove(this); 00087 } 00088 00089 // LLWatchdogTimeout 00090 LLWatchdogTimeout::LLWatchdogTimeout() : 00091 mTimeout(0.0f) 00092 { 00093 } 00094 00095 LLWatchdogTimeout::~LLWatchdogTimeout() 00096 { 00097 } 00098 00099 bool LLWatchdogTimeout::isAlive() const 00100 { 00101 return (mTimer.getStarted() && !mTimer.hasExpired()); 00102 } 00103 00104 void LLWatchdogTimeout::setTimeout(F32 d) 00105 { 00106 mTimeout = d; 00107 } 00108 00109 void LLWatchdogTimeout::start() 00110 { 00111 // Order of operation is very impmortant here. 00112 // After LLWatchdogEntry::start() is called 00113 // LLWatchdogTimeout::isAlive() will be called asynchronously. 00114 mTimer.start(); 00115 mTimer.setTimerExpirySec(mTimeout); 00116 LLWatchdogEntry::start(); 00117 } 00118 void LLWatchdogTimeout::stop() 00119 { 00120 LLWatchdogEntry::stop(); 00121 mTimer.stop(); 00122 } 00123 00124 void LLWatchdogTimeout::ping() 00125 { 00126 mTimer.setTimerExpirySec(mTimeout); 00127 } 00128 00129 // LlWatchdog 00130 LLWatchdog::LLWatchdog() : 00131 mSuspectsAccessMutex(NULL), 00132 mTimer(NULL) 00133 { 00134 } 00135 00136 LLWatchdog::~LLWatchdog() 00137 { 00138 } 00139 00140 void LLWatchdog::add(LLWatchdogEntry* e) 00141 { 00142 mSuspectsAccessMutex->lock(); 00143 mSuspects.insert(e); 00144 mSuspectsAccessMutex->unlock(); 00145 } 00146 00147 void LLWatchdog::remove(LLWatchdogEntry* e) 00148 { 00149 mSuspectsAccessMutex->lock(); 00150 mSuspects.erase(e); 00151 mSuspectsAccessMutex->unlock(); 00152 } 00153 00154 void LLWatchdog::init() 00155 { 00156 mSuspectsAccessMutex = new LLMutex(NULL); 00157 mTimer = new LLWatchdogTimerThread(); 00158 mTimer->setSleepTime(1000); 00159 mTimer->start(); 00160 } 00161 00162 void LLWatchdog::cleanup() 00163 { 00164 mTimer->stop(); 00165 delete mTimer; 00166 delete mSuspectsAccessMutex; 00167 } 00168 00169 void LLWatchdog::run() 00170 { 00171 mSuspectsAccessMutex->lock(); 00172 00173 SuspectsRegistry::iterator result = 00174 std::find_if(mSuspects.begin(), 00175 mSuspects.end(), 00176 std::not1(std::mem_fun(&LLWatchdogEntry::isAlive)) 00177 ); 00178 00179 if(result != mSuspects.end()) 00180 { 00181 // error!!! 00182 mTimer->stop(); 00183 00184 llinfos << "Watchdog detected error:" << llendl; 00185 #ifdef LL_WINDOWS 00186 RaiseException(0,0,0,0); 00187 #else 00188 raise(SIGQUIT); 00189 #endif 00190 } 00191 00192 mSuspectsAccessMutex->unlock(); 00193 }