llwatchdog.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:5k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llthreadwatchdog.cpp
  3.  * @brief The LLThreadWatchdog class definitions
  4.  *
  5.  * $LicenseInfo:firstyear=2007&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2007-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llwatchdog.h"
  34. const U32 WATCHDOG_SLEEP_TIME_USEC = 1000000;
  35. void default_killer_callback()
  36. {
  37. #ifdef LL_WINDOWS
  38. RaiseException(0,0,0,0);
  39. #else
  40. raise(SIGQUIT);
  41. #endif
  42. }
  43. // This class runs the watchdog timing thread.
  44. class LLWatchdogTimerThread : public LLThread
  45. {
  46. public:
  47. LLWatchdogTimerThread() : 
  48. LLThread("Watchdog"),
  49. mSleepMsecs(0),
  50. mStopping(false)
  51. {
  52. }
  53.             
  54. ~LLWatchdogTimerThread() {}
  55.     
  56. void setSleepTime(long ms) { mSleepMsecs = ms; }
  57. void stop() 
  58. {
  59. mStopping = true; 
  60. mSleepMsecs = 1;
  61. }
  62.     
  63. /* virtual */ void run()
  64. {
  65. while(!mStopping)
  66. {
  67. LLWatchdog::getInstance()->run();
  68. ms_sleep(mSleepMsecs);
  69. }
  70. }
  71. private:
  72. long mSleepMsecs;
  73. bool mStopping;
  74. };
  75. // LLWatchdogEntry
  76. LLWatchdogEntry::LLWatchdogEntry()
  77. {
  78. }
  79. LLWatchdogEntry::~LLWatchdogEntry()
  80. {
  81. stop();
  82. }
  83. void LLWatchdogEntry::start()
  84. {
  85. LLWatchdog::getInstance()->add(this);
  86. }
  87. void LLWatchdogEntry::stop()
  88. {
  89. LLWatchdog::getInstance()->remove(this);
  90. }
  91. // LLWatchdogTimeout
  92. const std::string UNINIT_STRING = "uninitialized";
  93. LLWatchdogTimeout::LLWatchdogTimeout() : 
  94. mTimeout(0.0f),
  95. mPingState(UNINIT_STRING)
  96. {
  97. }
  98. LLWatchdogTimeout::~LLWatchdogTimeout() 
  99. {
  100. }
  101. bool LLWatchdogTimeout::isAlive() const 
  102. return (mTimer.getStarted() && !mTimer.hasExpired()); 
  103. }
  104. void LLWatchdogTimeout::reset()
  105. {
  106. mTimer.setTimerExpirySec(mTimeout); 
  107. }
  108. void LLWatchdogTimeout::setTimeout(F32 d) 
  109. {
  110. mTimeout = d;
  111. }
  112. void LLWatchdogTimeout::start(const std::string& state) 
  113. {
  114. // Order of operation is very impmortant here.
  115. // After LLWatchdogEntry::start() is called
  116. // LLWatchdogTimeout::isAlive() will be called asynchronously. 
  117. mTimer.start(); 
  118. ping(state);
  119. LLWatchdogEntry::start();
  120. }
  121. void LLWatchdogTimeout::stop() 
  122. {
  123. LLWatchdogEntry::stop();
  124. mTimer.stop();
  125. }
  126. void LLWatchdogTimeout::ping(const std::string& state) 
  127. if(!state.empty())
  128. {
  129. mPingState = state;
  130. }
  131. reset();
  132. }
  133. // LLWatchdog
  134. LLWatchdog::LLWatchdog() :
  135. mSuspectsAccessMutex(NULL),
  136. mTimer(NULL),
  137. mLastClockCount(0),
  138. mKillerCallback(&default_killer_callback)
  139. {
  140. }
  141. LLWatchdog::~LLWatchdog()
  142. {
  143. }
  144. void LLWatchdog::add(LLWatchdogEntry* e)
  145. {
  146. lockThread();
  147. mSuspects.insert(e);
  148. unlockThread();
  149. }
  150. void LLWatchdog::remove(LLWatchdogEntry* e)
  151. {
  152. lockThread();
  153.     mSuspects.erase(e);
  154. unlockThread();
  155. }
  156. void LLWatchdog::init(killer_event_callback func)
  157. {
  158. mKillerCallback = func;
  159. if(!mSuspectsAccessMutex && !mTimer)
  160. {
  161. mSuspectsAccessMutex = new LLMutex(NULL);
  162. mTimer = new LLWatchdogTimerThread();
  163. mTimer->setSleepTime(WATCHDOG_SLEEP_TIME_USEC / 1000);
  164. mLastClockCount = LLTimer::getTotalTime();
  165. // mTimer->start() kicks off the thread, any code after
  166. // start needs to use the mSuspectsAccessMutex
  167. mTimer->start();
  168. }
  169. }
  170. void LLWatchdog::cleanup()
  171. {
  172. if(mTimer)
  173. {
  174. mTimer->stop();
  175. delete mTimer;
  176. mTimer = NULL;
  177. }
  178. if(mSuspectsAccessMutex)
  179. {
  180. delete mSuspectsAccessMutex;
  181. mSuspectsAccessMutex = NULL;
  182. }
  183. mLastClockCount = 0;
  184. }
  185. void LLWatchdog::run()
  186. {
  187. lockThread();
  188. // Check the time since the last call to run...
  189. // If the time elapsed is two times greater than the regualr sleep time
  190. // reset the active timeouts.
  191. const U32 TIME_ELAPSED_MULTIPLIER = 2;
  192. U64 current_time = LLTimer::getTotalTime();
  193. U64 current_run_delta = current_time - mLastClockCount;
  194. mLastClockCount = current_time;
  195. if(current_run_delta > (WATCHDOG_SLEEP_TIME_USEC * TIME_ELAPSED_MULTIPLIER))
  196. {
  197. llinfos << "Watchdog thread delayed: resetting entries." << llendl;
  198. std::for_each(mSuspects.begin(), 
  199. mSuspects.end(), 
  200. std::mem_fun(&LLWatchdogEntry::reset)
  201. );
  202. }
  203. else
  204. {
  205. SuspectsRegistry::iterator result = 
  206. std::find_if(mSuspects.begin(), 
  207. mSuspects.end(), 
  208. std::not1(std::mem_fun(&LLWatchdogEntry::isAlive))
  209. );
  210. if(result != mSuspects.end())
  211. {
  212. // error!!!
  213. if(mTimer)
  214. {
  215. mTimer->stop();
  216. }
  217. llinfos << "Watchdog detected error:" << llendl;
  218. mKillerCallback();
  219. }
  220. }
  221. unlockThread();
  222. }
  223. void LLWatchdog::lockThread()
  224. {
  225. if(mSuspectsAccessMutex != NULL)
  226. {
  227. mSuspectsAccessMutex->lock();
  228. }
  229. }
  230. void LLWatchdog::unlockThread()
  231. {
  232. if(mSuspectsAccessMutex != NULL)
  233. {
  234. mSuspectsAccessMutex->unlock();
  235. }
  236. }