#ifdef USE_PCH #include "pch.h" #else #include #include #include #include #include #include #include #include using namespace std; #include "sitecing/process_manager.h" #endif namespace sitecing { process_manager::process_manager() : min_children(1), max_children(MAX_SITECING_SCOREBOARD_SLOTS), min_spare_children(0), max_spare_children(-1), finishing(false), die_humbly(false) { } process_manager::~process_manager() { if(die_humbly) return; for(int tmp=0;tmpstate!=scoreboard_slot::state_free) && (sslot->pid>0)) kill(sslot->pid,SIGTERM); } collect_dead_souls(true); } void process_manager::manage() { while(!finishing) { manage_children(); // XXX: is it the way it should be? sleep(10); wait_for_children(); } collect_dead_souls(true); } void process_manager::collect_dead_souls(bool actively) { for(int tries=5;(tries>0) && (sboard.count_slots(scoreboard_slot::state_free)!=MAX_SITECING_SCOREBOARD_SLOTS);tries--) { if(actively) { for(int tmp=0;tmpstate!=scoreboard_slot::state_free) && (sslot->pid>0)) kill(sslot->pid,SIGTERM); } } wait_for_children(false); // XXX: again.. is it the right way? sleep(1); } } void process_manager::wait_for_children(bool hang) { int status; int o = WUNTRACED; if(!hang) o|=WNOHANG; while(sboard.count_slots(scoreboard_slot::state_free)state) { case scoreboard_slot::state_free: break; case scoreboard_slot::state_idle: idle_children++; default: total_children++; break; } } int total_lack = 0; if(total_children0 || total_lack>0) && (total_childrenstate==scoreboard_slot::state_idle) idle_children++; } int idle_excess = idle_children-max_spare_children; bool rv = false; for(int tmp=0;tmp0;tmp++) { scoreboard_slot *sslot = sboard.get_slot(tmp); if((sslot->state==scoreboard_slot::state_idle) && (sslot->pid>0)) { kill(sslot->pid,SIGTERM); idle_excess--; rv = true; } } return rv; } void process_manager::spawn_child() { int slot = sboard.allocate_slot(); pid_t pid = fork(); if(pid<0) { sboard.free_slot(slot); throw konforka::exception(CODEPOINT,"failed to fork()"); } if(!pid) { // child sboard.get_slot(slot)->pid = getpid(); process(slot); _exit(0); } // parent sboard.get_slot(slot)->pid = pid; } }