//-------------------------------------------------------------------------------------------------- static void SigChildHandler ( int sigNum ) { // More than one child may have changed state so keep checking until we get all of them. while (1) { // Get the pid of the child process that changed state but do not reap the child so that we // can look at the child process's info. pid_t pid = wait_Peek(); if (pid == 0) { // No more children have terminated. break; } // Send the pid to the apps SIGCHILD handler for processing. le_result_t result = apps_SigChildHandler(pid); if (result == LE_FAULT) { // There was an app fault that could not be handled so restart the framework. Reboot(); } if (result == LE_NOT_FOUND) { // Send the pid to the framework daemon's SIGCHILD handler for processing. le_result_t r = fwDaemons_SigChildHandler(pid); if (r == LE_FAULT) { CaptureDebugData(); Reboot(); } else if (r == LE_NOT_FOUND) { // The child is neither an application process nor a framework daemon. // Reap the child now. wait_ReapChild(pid); LE_CRIT("Unknown child process %d.", pid); } } } }
//-------------------------------------------------------------------------------------------------- proc_FaultAction_t proc_SigChildHandler ( proc_Ref_t procRef, ///< [IN] The process reference. int procExitStatus ///< [IN] The status of the process given by wait(). ) { proc_FaultAction_t faultAction = PROC_FAULT_ACTION_NO_FAULT; if (WIFSTOPPED(procExitStatus)) { procRef->paused = true; LE_INFO("Process '%s' (PID: %d) has paused.", procRef->name, procRef->pid); } else if (WIFCONTINUED(procExitStatus)) { procRef->paused = false; LE_INFO("Process '%s' (PID: %d) has been continued.", procRef->name, procRef->pid); } else { // The process died. if (WIFEXITED(procExitStatus)) { LE_INFO("Process '%s' (PID: %d) has exited with exit code %d.", procRef->name, procRef->pid, WEXITSTATUS(procExitStatus)); if (WEXITSTATUS(procExitStatus) != EXIT_SUCCESS) { faultAction = GetFaultAction(procRef); } } else if (WIFSIGNALED(procExitStatus)) { int sig = WTERMSIG(procExitStatus); // WARNING: strsignal() is non-reentrant. We use it here because the Supervisor is // single threaded. LE_INFO("Process '%s' (PID: %d) has exited due to signal %d (%s).", procRef->name, procRef->pid, sig, strsignal(sig)); faultAction = GetFaultAction(procRef); } // Check the fault action. If it indicates that the process stopped due to an error, save // all relevant data for future diagnosis. if (faultAction != PROC_FAULT_ACTION_NO_FAULT) { // Check if we're rebooting. If we are, this data needs to be saved in a more permanent // location. bool isRebooting = faultAction == PROC_FAULT_ACTION_REBOOT; CaptureDebugData(procRef, isRebooting); } procRef->pid = -1; procRef->paused = false; } return faultAction; }