aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon/llheartbeat.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llcommon/llheartbeat.cpp')
-rw-r--r--linden/indra/llcommon/llheartbeat.cpp165
1 files changed, 165 insertions, 0 deletions
diff --git a/linden/indra/llcommon/llheartbeat.cpp b/linden/indra/llcommon/llheartbeat.cpp
new file mode 100644
index 0000000..13bcd46
--- /dev/null
+++ b/linden/indra/llcommon/llheartbeat.cpp
@@ -0,0 +1,165 @@
1/**
2 * @file llheartbeat.cpp
3 * @brief Class encapsulating logic for telling a watchdog that we live.
4 *
5 * $LicenseInfo:firstyear=2008&license=viewergpl$
6 *
7 * Copyright (c) 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#include <errno.h>
33#include <signal.h>
34
35#include "linden_common.h"
36#include "llapp.h"
37
38#include "llheartbeat.h"
39
40LLHeartbeat::LLHeartbeat(F32 secs_between_heartbeat,
41 F32 aggressive_heartbeat_panic_secs,
42 F32 aggressive_heartbeat_max_blocking_secs)
43 : mSecsBetweenHeartbeat(secs_between_heartbeat),
44 mAggressiveHeartbeatPanicSecs(aggressive_heartbeat_panic_secs),
45 mAggressiveHeartbeatMaxBlockingSecs(aggressive_heartbeat_max_blocking_secs),
46 mSuppressed(false)
47{
48 mBeatTimer.reset();
49 mBeatTimer.setTimerExpirySec(mSecsBetweenHeartbeat);
50 mPanicTimer.reset();
51 mPanicTimer.setTimerExpirySec(mAggressiveHeartbeatPanicSecs);
52}
53
54LLHeartbeat::~LLHeartbeat()
55{
56 // do nothing.
57}
58
59void
60LLHeartbeat::setSuppressed(bool is_suppressed)
61{
62 mSuppressed = is_suppressed;
63}
64
65// returns 0 on success, -1 on permanent failure, 1 on temporary failure
66int
67LLHeartbeat::rawSend()
68{
69#if LL_WINDOWS
70 return 0; // Pretend we succeeded.
71#else
72 if (mSuppressed)
73 return 0; // Pretend we succeeded.
74
75 union sigval dummy;
76 int result = sigqueue(getppid(), LL_HEARTBEAT_SIGNAL, dummy);
77 if (result == 0)
78 return 0; // success
79
80 int err = errno;
81 if (err == EAGAIN)
82 return 1; // failed to queue, try again
83
84 return -1; // other failure.
85#endif
86}
87
88int
89LLHeartbeat::rawSendWithTimeout(F32 timeout_sec)
90{
91 int result = 0;
92
93 // Spin tightly until our heartbeat is digested by the watchdog
94 // or we time-out. We don't really want to sleep because our
95 // wake-up time might be undesirably synchronised to a hidden
96 // clock by the system's scheduler.
97 mTimeoutTimer.reset();
98 mTimeoutTimer.setTimerExpirySec(timeout_sec);
99 do {
100 result = rawSend();
101 //llinfos << " HEARTSENDc=" << result << llendl;
102 } while (result==1 && !mTimeoutTimer.hasExpired());
103
104 return result;
105}
106
107bool
108LLHeartbeat::send(F32 timeout_sec)
109{
110 bool total_success = false;
111 int result = 1;
112
113 if (timeout_sec > 0.f) {
114 // force a spin until success or timeout
115 result = rawSendWithTimeout(timeout_sec);
116 } else {
117 if (mBeatTimer.hasExpired()) {
118 // zero-timeout; we don't care too much whether our
119 // heartbeat was digested.
120 result = rawSend();
121 //llinfos << " HEARTSENDb=" << result << llendl;
122 }
123 }
124
125 if (result == -1) {
126 // big failure.
127 } else if (result == 0) {
128 total_success = true;
129 } else {
130 // need to retry at some point
131 }
132
133 if (total_success) {
134 mBeatTimer.reset();
135 mBeatTimer.setTimerExpirySec(mSecsBetweenHeartbeat);
136 // reset the time until we start panicking about lost
137 // heartbeats again.
138 mPanicTimer.reset();
139 mPanicTimer.setTimerExpirySec(mAggressiveHeartbeatPanicSecs);
140 } else {
141 // leave mBeatTimer as expired so we'll lazily poke the
142 // watchdog again next time through.
143 }
144
145 if (mPanicTimer.hasExpired()) {
146 // It's been ages since we successfully had a heartbeat
147 // digested by the watchdog. Sit here and spin a while
148 // in the hope that we can force it through.
149 llwarns << "Unable to deliver heartbeat to launcher for " << mPanicTimer.getElapsedTimeF32() << " seconds. Going to try very hard for up to " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << llendl;
150 result = rawSendWithTimeout(mAggressiveHeartbeatMaxBlockingSecs);
151 if (result == 0) {
152 total_success = true;
153 } else {
154 // we couldn't even force it through. That's bad,
155 // but we'll try again in a while.
156 llwarns << "Could not deliver heartbeat to launcher even after trying very hard for " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << llendl;
157 }
158
159 // in any case, reset the panic timer.
160 mPanicTimer.reset();
161 mPanicTimer.setTimerExpirySec(mAggressiveHeartbeatPanicSecs);
162 }
163
164 return total_success;
165}