aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llwatchdog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/newview/llwatchdog.cpp')
-rw-r--r--linden/indra/newview/llwatchdog.cpp222
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.
37class LLWatchdogTimerThread : public LLThread
38{
39public:
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
65private:
66 long mSleepMsecs;
67 bool mStopping;
68};
69
70// LLWatchdogEntry
71LLWatchdogEntry::LLWatchdogEntry()
72{
73}
74
75LLWatchdogEntry::~LLWatchdogEntry()
76{
77}
78
79void LLWatchdogEntry::start()
80{
81 LLWatchdog::getInstance()->add(this);
82}
83
84void LLWatchdogEntry::stop()
85{
86 LLWatchdog::getInstance()->remove(this);
87}
88
89// LLWatchdogTimeout
90LLWatchdogTimeout::LLWatchdogTimeout() :
91 mTimeout(0.0f)
92{
93}
94
95LLWatchdogTimeout::~LLWatchdogTimeout()
96{
97}
98
99bool LLWatchdogTimeout::isAlive() const
100{
101 return (mTimer.getStarted() && !mTimer.hasExpired());
102}
103
104void LLWatchdogTimeout::setTimeout(F32 d)
105{
106 mTimeout = d;
107}
108
109void 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}
118void LLWatchdogTimeout::stop()
119{
120 LLWatchdogEntry::stop();
121 mTimer.stop();
122}
123
124void LLWatchdogTimeout::ping()
125{
126 mTimer.setTimerExpirySec(mTimeout);
127}
128
129// LlWatchdog
130LLWatchdog::LLWatchdog() :
131 mSuspectsAccessMutex(NULL),
132 mTimer(NULL)
133{
134}
135
136LLWatchdog::~LLWatchdog()
137{
138}
139
140void LLWatchdog::add(LLWatchdogEntry* e)
141{
142 lockThread();
143 mSuspects.insert(e);
144 unlockThread();
145}
146
147void LLWatchdog::remove(LLWatchdogEntry* e)
148{
149 lockThread();
150 mSuspects.erase(e);
151 unlockThread();
152}
153
154void 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
165void 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
179void 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
208void LLWatchdog::lockThread()
209{
210 if(mSuspectsAccessMutex != NULL)
211 {
212 mSuspectsAccessMutex->lock();
213 }
214}
215
216void LLWatchdog::unlockThread()
217{
218 if(mSuspectsAccessMutex != NULL)
219 {
220 mSuspectsAccessMutex->unlock();
221 }
222}