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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llerrorthread.cpp
  3.  *
  4.  * $LicenseInfo:firstyear=2004&license=viewergpl$
  5.  * 
  6.  * Copyright (c) 2004-2010, Linden Research, Inc.
  7.  * 
  8.  * Second Life Viewer Source Code
  9.  * The source code in this file ("Source Code") is provided by Linden Lab
  10.  * to you under the terms of the GNU General Public License, version 2.0
  11.  * ("GPL"), unless you have obtained a separate licensing agreement
  12.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  13.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  14.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  15.  * 
  16.  * There are special exceptions to the terms and conditions of the GPL as
  17.  * it is applied to this Source Code. View the full text of the exception
  18.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  19.  * online at
  20.  * 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. #include "linden_common.h"
  32. #include "llerrorthread.h"
  33. #include "llapp.h"
  34. #include "lltimer.h" // ms_sleep()
  35. LLErrorThread::LLErrorThread()
  36. : LLThread("Error"),
  37.   mUserDatap(NULL)
  38. {
  39. }
  40. LLErrorThread::~LLErrorThread()
  41. {
  42. }
  43. void LLErrorThread::setUserData(void* user_data)
  44. {
  45. mUserDatap = user_data;
  46. }
  47. void* LLErrorThread::getUserData() const
  48. {
  49. return mUserDatap;
  50. }
  51. #if !LL_WINDOWS
  52. //
  53. // Various signal/error handling functions that can't be put into the class
  54. //
  55. void get_child_status(const int waitpid_status, int &process_status, bool &exited, bool do_logging)
  56. {
  57. exited = false;
  58. process_status = -1;
  59. // The child process exited.  Call its callback, and then clean it up
  60. if (WIFEXITED(waitpid_status))
  61. {
  62. process_status = WEXITSTATUS(waitpid_status);
  63. exited = true;
  64. if (do_logging)
  65. {
  66. llinfos << "get_child_status - Child exited cleanly with return of " << process_status << llendl;
  67. }
  68. return;
  69. }
  70. else if (WIFSIGNALED(waitpid_status))
  71. {
  72. process_status = WTERMSIG(waitpid_status);
  73. exited = true;
  74. if (do_logging)
  75. {
  76. llinfos << "get_child_status - Child died because of uncaught signal " << process_status << llendl;
  77. #ifdef WCOREDUMP
  78. if (WCOREDUMP(waitpid_status))
  79. {
  80. llinfos << "get_child_status - Child dumped core" << llendl;
  81. }
  82. else
  83. {
  84. llinfos << "get_child_status - Child didn't dump core" << llendl;
  85. }
  86. #endif
  87. }
  88. return;
  89. }
  90. else if (do_logging)
  91. {
  92. // This is weird.  I just dump the waitpid status into the status code,
  93. // not that there's any way of telling what it is...
  94. llinfos << "get_child_status - Got SIGCHILD but child didn't exit" << llendl;
  95. process_status = waitpid_status;
  96. }
  97. }
  98. #endif
  99. void LLErrorThread::run()
  100. {
  101. LLApp::sErrorThreadRunning = TRUE;
  102. // This thread sits and waits for the sole purpose
  103. // of waiting for the signal/exception handlers to flag the
  104. // application state as APP_STATUS_ERROR.
  105. llinfos << "thread_error - Waiting for an error" << llendl;
  106. S32 counter = 0;
  107. #if !LL_WINDOWS
  108. U32 last_sig_child_count = 0;
  109. #endif
  110. while (1)
  111. {
  112. if (LLApp::isError() || LLApp::isStopped())
  113. {
  114. // The application has stopped running, time to take action (maybe)
  115. break;
  116. }
  117. #if !LL_WINDOWS
  118. // Check whether or not the main thread had a sig child we haven't handled.
  119. U32 current_sig_child_count = LLApp::getSigChildCount();
  120. if (last_sig_child_count != current_sig_child_count)
  121. {
  122. int status = 0;
  123. pid_t child_pid = 0;
  124. last_sig_child_count = current_sig_child_count;
  125. if (LLApp::sLogInSignal)
  126. {
  127. llinfos << "thread_error handling SIGCHLD #" << current_sig_child_count << llendl;
  128. }
  129. for (LLApp::child_map::iterator iter = LLApp::sChildMap.begin(); iter != LLApp::sChildMap.end();)
  130. {
  131. child_pid = iter->first;
  132. LLChildInfo &child_info = iter->second;
  133. // check the status of *all* children, in case we missed a signal
  134. if (0 != waitpid(child_pid, &status, WNOHANG))
  135. {
  136. bool exited = false;
  137. int exit_status = -1;
  138. get_child_status(status, exit_status, exited, LLApp::sLogInSignal);
  139. if (child_info.mCallback)
  140. {
  141. if (LLApp::sLogInSignal)
  142. {
  143. llinfos << "Signal handler - Running child callback" << llendl;
  144. }
  145. child_info.mCallback(child_pid, exited, status);
  146. }
  147. LLApp::sChildMap.erase(iter++);
  148. }
  149. else
  150. {
  151. // Child didn't terminate, yet we got a sigchild somewhere...
  152. if (child_info.mGotSigChild && child_info.mCallback)
  153. {
  154. child_info.mCallback(child_pid, false, 0);
  155. }
  156. child_info.mGotSigChild = FALSE;
  157. iter++;
  158. }
  159. }
  160. // check the status of *all* children, in case we missed a signal
  161. // Same as above, but use the default child callback
  162. while(0 < (child_pid = waitpid( -1, &status, WNOHANG )))
  163. {
  164. if (0 != waitpid(child_pid, &status, WNOHANG))
  165. {
  166. bool exited = false;
  167. int exit_status = -1;
  168. get_child_status(status, exit_status, exited, LLApp::sLogInSignal);
  169. if (LLApp::sDefaultChildCallback)
  170. {
  171. if (LLApp::sLogInSignal)
  172. {
  173. llinfos << "Signal handler - Running default child callback" << llendl;
  174. }
  175. LLApp::sDefaultChildCallback(child_pid, true, status);
  176. }
  177. }
  178. }
  179. }
  180. #endif
  181. ms_sleep(10);
  182. counter++;
  183. }
  184. if (LLApp::isError())
  185. {
  186. // The app is in an error state, run the application's error handler.
  187. //llinfos << "thread_error - An error has occurred, running error callback!" << llendl;
  188. // Run the error handling callback
  189. LLApp::runErrorHandler();
  190. }
  191. else
  192. {
  193. // Everything is okay, a clean exit.
  194. //llinfos << "thread_error - Application exited cleanly" << llendl;
  195. }
  196. //llinfos << "thread_error - Exiting" << llendl;
  197. LLApp::sErrorThreadRunning = FALSE;
  198. }