void SIGCHLD_handler(int s) { int old_errno = errno; int child_status = 0, child_pid = 0; pid_t appmon_pid = getpid(); SWI_LOG("APPMON", DEBUG, "SIGCHLD_handler: appmon_pid=%d =============>\n", appmon_pid); while (1) { do { errno = 0; //call waitpid trying to avoid suspend-related state changes.(no WUNTRACED or WCONTINUED options to waitpid) child_pid = waitpid(WAIT_ANY, &child_status, WNOHANG); } while (child_pid <= 0 && errno == EINTR); if (child_pid <= 0) { /* A real failure means there are no more stopped or terminated child processes, so return. */ errno = old_errno; SWI_LOG("APPMON", DEBUG, "SIGCHLD_handler: pid=%d =============< quit\n", appmon_pid); fflush(stdout); return; } app_t* app = find_by_pid(child_pid); if (NULL != app) { int exited = WIFEXITED(child_status); int exited_code = exited ? WEXITSTATUS(child_status) : -1; int signaled = WIFSIGNALED(child_status); //update exit status only if process is terminated. //if stopped/continued event on process is caught, don't update status if (!exited && !signaled) { SWI_LOG("APPMON", ERROR, "SIGCHLD_handler: status change looks like suspend events (STOP/CONT), ignored\n"); continue; //go to next waipid call } //real child termination, update values app->last_exit_code = child_status; app_exit_status(app); SWI_LOG("APPMON", DEBUG, "SIGCHLD_handler: app terminated: id=%d, prog=%s was pid %d, calculated status =%s\n", app->id, app->prog, child_pid, app->last_exit_status); if (TO_BE_KILLED == app->status || (STARTED == app->status && exited && !exited_code)) { //put flag to be used it stop_app app->status = KILLED; SWI_LOG("APPMON", DEBUG, "SIGCHLD_handler: status => KILLED\n"); } else { if ((exited && exited_code > 0) | signaled) { SWI_LOG("APPMON", DEBUG, "SIGCHLD_handler: Child status error %d, application is set to TO_BE_RESTARTED, %s\n", child_status, app->prog); //error has occur, restart app after delay // app will not be found if it has been stopped voluntarily, so it won't be restarted. app->status = TO_BE_RESTARTED; alarm(RESTART_DELAY); } } } else //app == NULL, pid not found in monitored apps { SWI_LOG("APPMON", DEBUG, "SIGCHLD_handler: unknown dead app, pid=%d\n", child_pid); } } }
//handler para tratar SIGCHLD static void sigchld_hand(int signo, siginfo_t *info, void *data) { waitpid(info->si_pid, NULL, 0); vector_remove(job_list, find_by_pid(job_list, info->si_pid)); }
void* remove_by_pid(Vector vector, pid_t pid){ return vector_remove(vector, find_by_pid(vector, pid)); }