diff options
Diffstat (limited to 'linden/indra/newview/llwatchdog.cpp')
-rw-r--r-- | linden/indra/newview/llwatchdog.cpp | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/linden/indra/newview/llwatchdog.cpp b/linden/indra/newview/llwatchdog.cpp new file mode 100644 index 0000000..1dd984e --- /dev/null +++ b/linden/indra/newview/llwatchdog.cpp | |||
@@ -0,0 +1,222 @@ | |||
1 | /** | ||
2 | * @file llthreadwatchdog.cpp | ||
3 | * @brief The LLThreadWatchdog class definitions | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2007&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2007-2008, 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 http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
21 | * | ||
22 | * By copying, modifying or distributing this software, you acknowledge | ||
23 | * that you have read and understood your obligations described above, | ||
24 | * and agree to abide by those obligations. | ||
25 | * | ||
26 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
27 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
28 | * COMPLETENESS OR PERFORMANCE. | ||
29 | * $/LicenseInfo$ | ||
30 | */ | ||
31 | |||
32 | |||
33 | #include "llviewerprecompiledheaders.h" | ||
34 | #include "llwatchdog.h" | ||
35 | |||
36 | // This class runs the watchdog timing thread. | ||
37 | class LLWatchdogTimerThread : public LLThread | ||
38 | { | ||
39 | public: | ||
40 | LLWatchdogTimerThread() : | ||
41 | LLThread("Watchdog"), | ||
42 | mSleepMsecs(0), | ||
43 | mStopping(false) | ||
44 | { | ||
45 | } | ||
46 | |||
47 | ~LLWatchdogTimerThread() {} | ||
48 | |||
49 | void setSleepTime(long ms) { mSleepMsecs = ms; } | ||
50 | void stop() | ||
51 | { | ||
52 | mStopping = true; | ||
53 | ms_sleep(1); | ||
54 | } | ||
55 | |||
56 | /* virtual */ void run() | ||
57 | { | ||
58 | while(!mStopping) | ||
59 | { | ||
60 | LLWatchdog::getInstance()->run(); | ||
61 | ms_sleep(mSleepMsecs); | ||
62 | } | ||
63 | } | ||
64 | |||
65 | private: | ||
66 | long mSleepMsecs; | ||
67 | bool mStopping; | ||
68 | }; | ||
69 | |||
70 | // LLWatchdogEntry | ||
71 | LLWatchdogEntry::LLWatchdogEntry() | ||
72 | { | ||
73 | } | ||
74 | |||
75 | LLWatchdogEntry::~LLWatchdogEntry() | ||
76 | { | ||
77 | } | ||
78 | |||
79 | void LLWatchdogEntry::start() | ||
80 | { | ||
81 | LLWatchdog::getInstance()->add(this); | ||
82 | } | ||
83 | |||
84 | void LLWatchdogEntry::stop() | ||
85 | { | ||
86 | LLWatchdog::getInstance()->remove(this); | ||
87 | } | ||
88 | |||
89 | // LLWatchdogTimeout | ||
90 | LLWatchdogTimeout::LLWatchdogTimeout() : | ||
91 | mTimeout(0.0f) | ||
92 | { | ||
93 | } | ||
94 | |||
95 | LLWatchdogTimeout::~LLWatchdogTimeout() | ||
96 | { | ||
97 | } | ||
98 | |||
99 | bool LLWatchdogTimeout::isAlive() const | ||
100 | { | ||
101 | return (mTimer.getStarted() && !mTimer.hasExpired()); | ||
102 | } | ||
103 | |||
104 | void LLWatchdogTimeout::setTimeout(F32 d) | ||
105 | { | ||
106 | mTimeout = d; | ||
107 | } | ||
108 | |||
109 | void LLWatchdogTimeout::start() | ||
110 | { | ||
111 | // Order of operation is very impmortant here. | ||
112 | // After LLWatchdogEntry::start() is called | ||
113 | // LLWatchdogTimeout::isAlive() will be called asynchronously. | ||
114 | mTimer.start(); | ||
115 | mTimer.setTimerExpirySec(mTimeout); | ||
116 | LLWatchdogEntry::start(); | ||
117 | } | ||
118 | void LLWatchdogTimeout::stop() | ||
119 | { | ||
120 | LLWatchdogEntry::stop(); | ||
121 | mTimer.stop(); | ||
122 | } | ||
123 | |||
124 | void LLWatchdogTimeout::ping() | ||
125 | { | ||
126 | mTimer.setTimerExpirySec(mTimeout); | ||
127 | } | ||
128 | |||
129 | // LlWatchdog | ||
130 | LLWatchdog::LLWatchdog() : | ||
131 | mSuspectsAccessMutex(NULL), | ||
132 | mTimer(NULL) | ||
133 | { | ||
134 | } | ||
135 | |||
136 | LLWatchdog::~LLWatchdog() | ||
137 | { | ||
138 | } | ||
139 | |||
140 | void LLWatchdog::add(LLWatchdogEntry* e) | ||
141 | { | ||
142 | lockThread(); | ||
143 | mSuspects.insert(e); | ||
144 | unlockThread(); | ||
145 | } | ||
146 | |||
147 | void LLWatchdog::remove(LLWatchdogEntry* e) | ||
148 | { | ||
149 | lockThread(); | ||
150 | mSuspects.erase(e); | ||
151 | unlockThread(); | ||
152 | } | ||
153 | |||
154 | void LLWatchdog::init() | ||
155 | { | ||
156 | if(!mSuspectsAccessMutex && !mTimer) | ||
157 | { | ||
158 | mSuspectsAccessMutex = new LLMutex(NULL); | ||
159 | mTimer = new LLWatchdogTimerThread(); | ||
160 | mTimer->setSleepTime(1000); | ||
161 | mTimer->start(); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | void LLWatchdog::cleanup() | ||
166 | { | ||
167 | if(mTimer) | ||
168 | { | ||
169 | mTimer->stop(); | ||
170 | delete mTimer; | ||
171 | } | ||
172 | |||
173 | if(mSuspectsAccessMutex) | ||
174 | { | ||
175 | delete mSuspectsAccessMutex; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | void LLWatchdog::run() | ||
180 | { | ||
181 | lockThread(); | ||
182 | |||
183 | SuspectsRegistry::iterator result = | ||
184 | std::find_if(mSuspects.begin(), | ||
185 | mSuspects.end(), | ||
186 | std::not1(std::mem_fun(&LLWatchdogEntry::isAlive)) | ||
187 | ); | ||
188 | |||
189 | if(result != mSuspects.end()) | ||
190 | { | ||
191 | // error!!! | ||
192 | if(mTimer) | ||
193 | { | ||
194 | mTimer->stop(); | ||
195 | } | ||
196 | |||
197 | llinfos << "Watchdog detected error:" << llendl; | ||
198 | #ifdef LL_WINDOWS | ||
199 | RaiseException(0,0,0,0); | ||
200 | #else | ||
201 | raise(SIGQUIT); | ||
202 | #endif | ||
203 | } | ||
204 | |||
205 | unlockThread(); | ||
206 | } | ||
207 | |||
208 | void LLWatchdog::lockThread() | ||
209 | { | ||
210 | if(mSuspectsAccessMutex != NULL) | ||
211 | { | ||
212 | mSuspectsAccessMutex->lock(); | ||
213 | } | ||
214 | } | ||
215 | |||
216 | void LLWatchdog::unlockThread() | ||
217 | { | ||
218 | if(mSuspectsAccessMutex != NULL) | ||
219 | { | ||
220 | mSuspectsAccessMutex->unlock(); | ||
221 | } | ||
222 | } | ||