PageRenderTime 40ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/llheartbeat.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 165 lines | 97 code | 20 blank | 48 comment | 22 complexity | 8f0aa8d37e1b2bbbffd03fa18363dcaf MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llheartbeat.cpp
  3. * @brief Class encapsulating logic for telling a watchdog that we live.
  4. *
  5. * $LicenseInfo:firstyear=2008&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include <errno.h>
  27. #include <signal.h>
  28. #include "linden_common.h"
  29. #include "llapp.h"
  30. #include "llheartbeat.h"
  31. LLHeartbeat::LLHeartbeat(F32 secs_between_heartbeat,
  32. F32 aggressive_heartbeat_panic_secs,
  33. F32 aggressive_heartbeat_max_blocking_secs)
  34. : mSecsBetweenHeartbeat(secs_between_heartbeat),
  35. mAggressiveHeartbeatPanicSecs(aggressive_heartbeat_panic_secs),
  36. mAggressiveHeartbeatMaxBlockingSecs(aggressive_heartbeat_max_blocking_secs),
  37. mSuppressed(false)
  38. {
  39. mBeatTimer.reset();
  40. mBeatTimer.setTimerExpirySec(mSecsBetweenHeartbeat);
  41. mPanicTimer.reset();
  42. mPanicTimer.setTimerExpirySec(mAggressiveHeartbeatPanicSecs);
  43. }
  44. LLHeartbeat::~LLHeartbeat()
  45. {
  46. // do nothing.
  47. }
  48. void
  49. LLHeartbeat::setSuppressed(bool is_suppressed)
  50. {
  51. mSuppressed = is_suppressed;
  52. }
  53. // returns 0 on success, -1 on permanent failure, 1 on temporary failure
  54. int
  55. LLHeartbeat::rawSend()
  56. {
  57. #if LL_WINDOWS
  58. return 0; // Pretend we succeeded.
  59. #else
  60. if (mSuppressed)
  61. return 0; // Pretend we succeeded.
  62. int result;
  63. #ifndef LL_DARWIN
  64. union sigval dummy;
  65. result = sigqueue(getppid(), LL_HEARTBEAT_SIGNAL, dummy);
  66. #else
  67. result = kill(getppid(), LL_HEARTBEAT_SIGNAL);
  68. #endif
  69. if (result == 0)
  70. return 0; // success
  71. int err = errno;
  72. if (err == EAGAIN)
  73. return 1; // failed to queue, try again
  74. return -1; // other failure.
  75. #endif
  76. }
  77. int
  78. LLHeartbeat::rawSendWithTimeout(F32 timeout_sec)
  79. {
  80. int result = 0;
  81. // Spin tightly until our heartbeat is digested by the watchdog
  82. // or we time-out. We don't really want to sleep because our
  83. // wake-up time might be undesirably synchronised to a hidden
  84. // clock by the system's scheduler.
  85. mTimeoutTimer.reset();
  86. mTimeoutTimer.setTimerExpirySec(timeout_sec);
  87. do {
  88. result = rawSend();
  89. //llinfos << " HEARTSENDc=" << result << llendl;
  90. } while (result==1 && !mTimeoutTimer.hasExpired());
  91. return result;
  92. }
  93. bool
  94. LLHeartbeat::send(F32 timeout_sec)
  95. {
  96. bool total_success = false;
  97. int result = 1;
  98. if (timeout_sec > 0.f) {
  99. // force a spin until success or timeout
  100. result = rawSendWithTimeout(timeout_sec);
  101. } else {
  102. if (mBeatTimer.hasExpired()) {
  103. // zero-timeout; we don't care too much whether our
  104. // heartbeat was digested.
  105. result = rawSend();
  106. //llinfos << " HEARTSENDb=" << result << llendl;
  107. }
  108. }
  109. if (result == -1) {
  110. // big failure.
  111. } else if (result == 0) {
  112. total_success = true;
  113. } else {
  114. // need to retry at some point
  115. }
  116. if (total_success) {
  117. mBeatTimer.reset();
  118. mBeatTimer.setTimerExpirySec(mSecsBetweenHeartbeat);
  119. // reset the time until we start panicking about lost
  120. // heartbeats again.
  121. mPanicTimer.reset();
  122. mPanicTimer.setTimerExpirySec(mAggressiveHeartbeatPanicSecs);
  123. } else {
  124. // leave mBeatTimer as expired so we'll lazily poke the
  125. // watchdog again next time through.
  126. }
  127. if (mPanicTimer.hasExpired()) {
  128. // It's been ages since we successfully had a heartbeat
  129. // digested by the watchdog. Sit here and spin a while
  130. // in the hope that we can force it through.
  131. llwarns << "Unable to deliver heartbeat to launcher for " << mPanicTimer.getElapsedTimeF32() << " seconds. Going to try very hard for up to " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << llendl;
  132. result = rawSendWithTimeout(mAggressiveHeartbeatMaxBlockingSecs);
  133. if (result == 0) {
  134. total_success = true;
  135. } else {
  136. // we couldn't even force it through. That's bad,
  137. // but we'll try again in a while.
  138. llwarns << "Could not deliver heartbeat to launcher even after trying very hard for " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << llendl;
  139. }
  140. // in any case, reset the panic timer.
  141. mPanicTimer.reset();
  142. mPanicTimer.setTimerExpirySec(mAggressiveHeartbeatPanicSecs);
  143. }
  144. return total_success;
  145. }