llerrorthread.cpp

Go to the documentation of this file.
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 // Various signal/error handling functions that can't be put into the class
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         // The child process exited.  Call its callback, and then clean it up
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                 // This is weird.  I just dump the waitpid status into the status code,
00098                 // not that there's any way of telling what it is...
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         // This thread sits and waits for the sole purpose
00110         // of waiting for the signal/exception handlers to flag the
00111         // application state as APP_STATUS_ERROR.
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                         // The application has stopped running, time to take action (maybe)
00123                         break;
00124                 }
00125 #if !LL_WINDOWS
00126                 // Check whether or not the main thread had a sig child we haven't handled.
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                                 // check the status of *all* children, in case we missed a signal
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                                         // Child didn't terminate, yet we got a sigchild somewhere...
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                         // check the status of *all* children, in case we missed a signal
00171                         // Same as above, but use the default child callback
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                 // The app is in an error state, run the application's error handler.
00199                 //llinfos << "thread_error - An error has occurred, running error callback!" << llendl;
00200                 // Run the error handling callback
00201                 LLApp::runErrorHandler();
00202         }
00203         else
00204         {
00205                 // Everything is okay, a clean exit.
00206                 //llinfos << "thread_error - Application exited cleanly" << llendl;
00207         }
00208         
00209         //llinfos << "thread_error - Exiting" << llendl;
00210         LLApp::sErrorThreadRunning = FALSE;
00211 }
00212 

Generated on Thu Jul 1 06:08:29 2010 for Second Life Viewer by  doxygen 1.4.7