00001
00031 #include "linden_common.h"
00032 #include "llerrorthread.h"
00033 #include "llapp.h"
00034
00035 LLErrorThread::LLErrorThread()
00036 : LLThread("Error"),
00037 mUserDatap(NULL)
00038 {
00039 }
00040
00041 LLErrorThread::~LLErrorThread()
00042 {
00043 }
00044
00045 void LLErrorThread::setUserData(void* user_data)
00046 {
00047 mUserDatap = user_data;
00048 }
00049
00050
00051 void* LLErrorThread::getUserData() const
00052 {
00053 return mUserDatap;
00054 }
00055
00056 #if !LL_WINDOWS
00057
00058
00059
00060 void get_child_status(const int waitpid_status, int &process_status, bool &exited, bool do_logging)
00061 {
00062 exited = false;
00063 process_status = -1;
00064
00065 if (WIFEXITED(waitpid_status))
00066 {
00067 process_status = WEXITSTATUS(waitpid_status);
00068 exited = true;
00069 if (do_logging)
00070 {
00071 llinfos << "get_child_status - Child exited cleanly with return of " << process_status << llendl;
00072 }
00073 return;
00074 }
00075 else if (WIFSIGNALED(waitpid_status))
00076 {
00077 process_status = WTERMSIG(waitpid_status);
00078 exited = true;
00079 if (do_logging)
00080 {
00081 llinfos << "get_child_status - Child died because of uncaught signal " << process_status << llendl;
00082 #ifdef WCOREDUMP
00083 if (WCOREDUMP(waitpid_status))
00084 {
00085 llinfos << "get_child_status - Child dumped core" << llendl;
00086 }
00087 else
00088 {
00089 llinfos << "get_child_status - Child didn't dump core" << llendl;
00090 }
00091 #endif
00092 }
00093 return;
00094 }
00095 else if (do_logging)
00096 {
00097
00098
00099 llinfos << "get_child_status - Got SIGCHILD but child didn't exit" << llendl;
00100 process_status = waitpid_status;
00101 }
00102
00103 }
00104 #endif
00105
00106 void LLErrorThread::run()
00107 {
00108 LLApp::sErrorThreadRunning = TRUE;
00109
00110
00111
00112 llinfos << "thread_error - Waiting for an error" << llendl;
00113
00114 S32 counter = 0;
00115 #if !LL_WINDOWS
00116 U32 last_sig_child_count = 0;
00117 #endif
00118 while (1)
00119 {
00120 if (LLApp::isError() || LLApp::isStopped())
00121 {
00122
00123 break;
00124 }
00125 #if !LL_WINDOWS
00126
00127 U32 current_sig_child_count = LLApp::getSigChildCount();
00128 if (last_sig_child_count != current_sig_child_count)
00129 {
00130 int status = 0;
00131 pid_t child_pid = 0;
00132 last_sig_child_count = current_sig_child_count;
00133 if (LLApp::sLogInSignal)
00134 {
00135 llinfos << "thread_error handling SIGCHLD #" << current_sig_child_count << llendl;
00136 }
00137 for (LLApp::child_map::iterator iter = LLApp::sChildMap.begin(); iter != LLApp::sChildMap.end();)
00138 {
00139 child_pid = iter->first;
00140 LLChildInfo &child_info = iter->second;
00141
00142 if (0 != waitpid(child_pid, &status, WNOHANG))
00143 {
00144 bool exited = false;
00145 int exit_status = -1;
00146 get_child_status(status, exit_status, exited, LLApp::sLogInSignal);
00147
00148 if (child_info.mCallback)
00149 {
00150 if (LLApp::sLogInSignal)
00151 {
00152 llinfos << "Signal handler - Running child callback" << llendl;
00153 }
00154 child_info.mCallback(child_pid, exited, status);
00155 }
00156 LLApp::sChildMap.erase(iter++);
00157 }
00158 else
00159 {
00160
00161 if (child_info.mGotSigChild && child_info.mCallback)
00162 {
00163 child_info.mCallback(child_pid, false, 0);
00164 }
00165 child_info.mGotSigChild = FALSE;
00166 iter++;
00167 }
00168 }
00169
00170
00171
00172 while(0 < (child_pid = waitpid( -1, &status, WNOHANG )))
00173 {
00174 if (0 != waitpid(child_pid, &status, WNOHANG))
00175 {
00176 bool exited = false;
00177 int exit_status = -1;
00178 get_child_status(status, exit_status, exited, LLApp::sLogInSignal);
00179 if (LLApp::sDefaultChildCallback)
00180 {
00181 if (LLApp::sLogInSignal)
00182 {
00183 llinfos << "Signal handler - Running default child callback" << llendl;
00184 }
00185 LLApp::sDefaultChildCallback(child_pid, true, status);
00186 }
00187 }
00188 }
00189 }
00190
00191
00192 #endif
00193 ms_sleep(10);
00194 counter++;
00195 }
00196 if (LLApp::isError())
00197 {
00198
00199
00200
00201 LLApp::runErrorHandler();
00202 }
00203 else
00204 {
00205
00206
00207 }
00208
00209
00210 LLApp::sErrorThreadRunning = FALSE;
00211 }
00212