/* start new worker if needed */ void check_worker_population() { int x, now, target_number_of_workers; gm_log( GM_LOG_TRACE3, "check_worker_population()\n"); /* set current worker number */ count_current_worker(GM_ENABLED); /* check if status worker died */ if( shm[3] == -1 ) { make_new_child(GM_WORKER_STATUS); } /* keep up minimum population */ for (x = current_number_of_workers; x < mod_gm_opt->min_worker; x++) { make_new_child(GM_WORKER_MULTI); current_number_of_workers++; } /* check every second */ now = (int)time(NULL); if(last_time_increased >= now) return; target_number_of_workers = adjust_number_of_worker(mod_gm_opt->min_worker, mod_gm_opt->max_worker, current_number_of_workers, current_number_of_jobs); for (x = current_number_of_workers; x < target_number_of_workers; x++) { last_time_increased = now; /* top up the worker pool */ make_new_child(GM_WORKER_MULTI); } return; }
/* start new worker if needed */ void check_worker_population() { int x, now, status, target_number_of_workers; gm_log( GM_LOG_TRACE3, "check_worker_population()\n"); now = (int)time(NULL); /* collect finished workers */ while(waitpid(-1, &status, WNOHANG) > 0) gm_log( GM_LOG_TRACE, "waitpid() worker exited with: %d\n", status); /* set current worker number */ count_current_worker(GM_ENABLED); /* check last check time, force restart all worker if there is no result in 2 minutes */ if( shm[SHM_WORKER_LAST_CHECK] < (now - 120) ) { gm_log( GM_LOG_INFO, "no checks in 2minutes, restarting all workers\n", shm[SHM_WORKER_LAST_CHECK]); shm[SHM_WORKER_LAST_CHECK] = now; for(x=SHM_SHIFT; x < mod_gm_opt->max_worker+SHM_SHIFT; x++) { save_kill(shm[x], SIGINT); } sleep(3); for(x=SHM_SHIFT; x < mod_gm_opt->max_worker+SHM_SHIFT; x++) { save_kill(shm[x], SIGKILL); shm[x] = -1; } } /* check if status worker died */ if( shm[SHM_STATUS_WORKER_PID] == -1 ) { make_new_child(GM_WORKER_STATUS); } /* keep up minimum population */ for (x = current_number_of_workers; x < mod_gm_opt->min_worker; x++) { make_new_child(GM_WORKER_MULTI); current_number_of_workers++; } /* check every second if we need to increase worker population */ if(last_time_increased >= now) return; target_number_of_workers = adjust_number_of_worker(mod_gm_opt->min_worker, mod_gm_opt->max_worker, current_number_of_workers, current_number_of_jobs); for (x = current_number_of_workers; x < target_number_of_workers; x++) { last_time_increased = now; /* top up the worker pool */ make_new_child(GM_WORKER_MULTI); } return; }
/* stop all children */ void stop_children(int mode) { int status, chld; int waited = 0; int x; gm_log( GM_LOG_TRACE, "stop_children(%d)\n", mode); /* ignore some signals for now */ signal(SIGTERM, SIG_IGN); signal(SIGINT, SIG_IGN); /* * send term signal to our children * children will finish the current job and exit */ killpg(0, SIGTERM); while(current_number_of_workers > 0) { gm_log( GM_LOG_TRACE, "send SIGTERM\n"); save_kill(shm[SHM_STATUS_WORKER_PID], SIGTERM); for(x=SHM_SHIFT; x < mod_gm_opt->max_worker+SHM_SHIFT; x++) { save_kill(shm[x], SIGTERM); } while((chld = waitpid(-1, &status, WNOHANG)) != -1 && chld > 0) { gm_log( GM_LOG_TRACE, "wait() %d exited with %d\n", chld, status); } if(mode == GM_WORKER_RESTART) break; sleep(1); waited++; if(waited > GM_CHILD_SHUTDOWN_TIMEOUT) { break; } count_current_worker(GM_DISABLED); if(current_number_of_workers == 0) break; gm_log( GM_LOG_TRACE, "still waiting (%d) %d children missing...\n", waited, current_number_of_workers); } if(mode == GM_WORKER_STOP) { killpg(0, SIGINT); count_current_worker(GM_DISABLED); if(current_number_of_workers == 0) return; gm_log( GM_LOG_TRACE, "sending SIGINT...\n"); save_kill(shm[SHM_STATUS_WORKER_PID], SIGINT); for(x=SHM_SHIFT; x < mod_gm_opt->max_worker+SHM_SHIFT; x++) { save_kill(shm[x], SIGINT); } /* wait 3 more seconds*/ if(current_number_of_workers > 0) sleep(3); while((chld = waitpid(-1, &status, WNOHANG)) != -1 && chld > 0) { gm_log( GM_LOG_TRACE, "wait() %d exited with %d\n", chld, status); } /* kill them the hard way */ count_current_worker(GM_DISABLED); if(current_number_of_workers == 0) return; save_kill(shm[SHM_STATUS_WORKER_PID], SIGKILL); for(x=SHM_SHIFT; x < mod_gm_opt->max_worker+SHM_SHIFT; x++) { save_kill(shm[x], SIGKILL); } /* count children a last time */ count_current_worker(GM_DISABLED); if(current_number_of_workers == 0) return; /* this will kill us too */ gm_log( GM_LOG_ERROR, "exiting by SIGKILL...\n"); killpg(0, SIGKILL); } /* restore signal handlers for a clean exit */ signal(SIGINT, clean_exit); signal(SIGTERM,clean_exit); }