Added automated exit handler in Util::Procs.

This commit is contained in:
Thulinma 2013-03-19 14:41:07 +01:00
parent f2b4e1d1a4
commit bf69dacefd
3 changed files with 69 additions and 35 deletions

View file

@ -476,7 +476,6 @@ std::string & JSON::Value::toNetPacked(){
//check if this is legal
if (myType != OBJECT){
fprintf(stderr, "Error: Only objects may be NetPacked!\n");
abort();
return emptystring;
}
//if sneaky storage doesn't contain correct data, re-calculate it

View file

@ -18,11 +18,73 @@
#include <pwd.h>
#include <stdlib.h>
#include <stdio.h>
#include "timing.h"
std::map<pid_t, std::string> Util::Procs::plist;
std::map<pid_t, Util::TerminationNotifier> Util::Procs::exitHandlers;
bool Util::Procs::handler_set = false;
/// Called at exit of any program that used a Start* function.
/// Waits up to 2.5 seconds, then sends SIGINT signal to all managed processes.
/// After that waits up to 10 seconds for children to exit, then sends SIGKILL to
/// all remaining children. Waits one more second for cleanup to finish, then exits.
void Util::Procs::exit_handler(){
int waiting = 0;
while ( !plist.empty()){
Util::sleep(500);
if (++waiting > 5){
break;
}
}
if ( !plist.empty()){
std::map<pid_t, std::string> listcopy = plist;
std::map<pid_t, std::string>::iterator it;
for (it = listcopy.begin(); it != listcopy.end(); it++){
kill(( *it).first, SIGINT);
}
}
waiting = 0;
while ( !plist.empty()){
Util::sleep(500);
if (++waiting > 10){
break;
}
}
if ( !plist.empty()){
std::map<pid_t, std::string> listcopy = plist;
std::map<pid_t, std::string>::iterator it;
for (it = listcopy.begin(); it != listcopy.end(); it++){
kill(( *it).first, SIGKILL);
}
}
waiting = 0;
while ( !plist.empty()){
Util::sleep(100);
if (++waiting > 10){
break;
}
}
}
/// Sets up exit and childsig handlers.
/// Called by every Start* function.
void Util::Procs::setHandler(){
if ( !handler_set){
struct sigaction new_action;
new_action.sa_handler = childsig_handler;
sigemptyset( &new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGCHLD, &new_action, NULL);
atexit(exit_handler);
handler_set = true;
}
}
/// Used internally to capture child signals and update plist.
void Util::Procs::childsig_handler(int signum){
if (signum != SIGCHLD){
@ -107,14 +169,7 @@ pid_t Util::Procs::Start(std::string name, std::string cmd){
if (isActive(name)){
return getPid(name);
}
if ( !handler_set){
struct sigaction new_action;
new_action.sa_handler = Util::Procs::childsig_handler;
sigemptyset( &new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGCHLD, &new_action, NULL);
handler_set = true;
}
setHandler();
pid_t ret = fork();
if (ret == 0){
runCmd(cmd);
@ -143,14 +198,7 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2){
if (isActive(name)){
return getPid(name);
}
if ( !handler_set){
struct sigaction new_action;
new_action.sa_handler = Util::Procs::childsig_handler;
sigemptyset( &new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGCHLD, &new_action, NULL);
handler_set = true;
}
setHandler();
int pfildes[2];
if (pipe(pfildes) == -1){
#if DEBUG >= 1
@ -220,15 +268,7 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, st
if (isActive(name)){
return getPid(name);
}
if ( !handler_set){
struct sigaction new_action;
new_action.sa_handler = Util::Procs::childsig_handler;
sigemptyset( &new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGCHLD, &new_action, NULL);
handler_set = true;
}
setHandler();
int pfildes[2];
int pfildes2[2];
if (pipe(pfildes) == -1){
@ -346,14 +386,7 @@ pid_t Util::Procs::StartPiped(std::string name, char * argv[], int * fdin, int *
}
pid_t pid;
int pipein[2], pipeout[2], pipeerr[2];
if ( !handler_set){
struct sigaction new_action;
new_action.sa_handler = Util::Procs::childsig_handler;
sigemptyset( &new_action.sa_mask);
new_action.sa_flags = 0;
sigaction(SIGCHLD, &new_action, NULL);
handler_set = true;
}
setHandler();
if (fdin && *fdin == -1 && pipe(pipein) < 0){
#if DEBUG >= 1
std::cerr << "Pipe (in) creation failed for " << name << std::endl;

View file

@ -18,8 +18,10 @@ namespace Util {
static std::map<pid_t, TerminationNotifier> exitHandlers; ///< termination function, if any
static bool handler_set; ///< If true, the sigchld handler has been setup.
static void childsig_handler(int signum);
static void exit_handler();
static void runCmd(std::string & cmd);
public:
static void setHandler();
public:
static pid_t Start(std::string name, std::string cmd);
static pid_t Start(std::string name, std::string cmd, std::string cmd2);
static pid_t Start(std::string name, std::string cmd, std::string cmd2, std::string cmd3);