Added automated exit handler in Util::Procs.
This commit is contained in:
parent
f2b4e1d1a4
commit
bf69dacefd
3 changed files with 69 additions and 35 deletions
|
@ -476,7 +476,6 @@ std::string & JSON::Value::toNetPacked(){
|
||||||
//check if this is legal
|
//check if this is legal
|
||||||
if (myType != OBJECT){
|
if (myType != OBJECT){
|
||||||
fprintf(stderr, "Error: Only objects may be NetPacked!\n");
|
fprintf(stderr, "Error: Only objects may be NetPacked!\n");
|
||||||
abort();
|
|
||||||
return emptystring;
|
return emptystring;
|
||||||
}
|
}
|
||||||
//if sneaky storage doesn't contain correct data, re-calculate it
|
//if sneaky storage doesn't contain correct data, re-calculate it
|
||||||
|
|
|
@ -18,11 +18,73 @@
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "timing.h"
|
||||||
|
|
||||||
std::map<pid_t, std::string> Util::Procs::plist;
|
std::map<pid_t, std::string> Util::Procs::plist;
|
||||||
std::map<pid_t, Util::TerminationNotifier> Util::Procs::exitHandlers;
|
std::map<pid_t, Util::TerminationNotifier> Util::Procs::exitHandlers;
|
||||||
bool Util::Procs::handler_set = false;
|
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.
|
/// Used internally to capture child signals and update plist.
|
||||||
void Util::Procs::childsig_handler(int signum){
|
void Util::Procs::childsig_handler(int signum){
|
||||||
if (signum != SIGCHLD){
|
if (signum != SIGCHLD){
|
||||||
|
@ -107,14 +169,7 @@ pid_t Util::Procs::Start(std::string name, std::string cmd){
|
||||||
if (isActive(name)){
|
if (isActive(name)){
|
||||||
return getPid(name);
|
return getPid(name);
|
||||||
}
|
}
|
||||||
if ( !handler_set){
|
setHandler();
|
||||||
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;
|
|
||||||
}
|
|
||||||
pid_t ret = fork();
|
pid_t ret = fork();
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
runCmd(cmd);
|
runCmd(cmd);
|
||||||
|
@ -143,14 +198,7 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2){
|
||||||
if (isActive(name)){
|
if (isActive(name)){
|
||||||
return getPid(name);
|
return getPid(name);
|
||||||
}
|
}
|
||||||
if ( !handler_set){
|
setHandler();
|
||||||
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;
|
|
||||||
}
|
|
||||||
int pfildes[2];
|
int pfildes[2];
|
||||||
if (pipe(pfildes) == -1){
|
if (pipe(pfildes) == -1){
|
||||||
#if DEBUG >= 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)){
|
if (isActive(name)){
|
||||||
return getPid(name);
|
return getPid(name);
|
||||||
}
|
}
|
||||||
if ( !handler_set){
|
setHandler();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pfildes[2];
|
int pfildes[2];
|
||||||
int pfildes2[2];
|
int pfildes2[2];
|
||||||
if (pipe(pfildes) == -1){
|
if (pipe(pfildes) == -1){
|
||||||
|
@ -346,14 +386,7 @@ pid_t Util::Procs::StartPiped(std::string name, char * argv[], int * fdin, int *
|
||||||
}
|
}
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int pipein[2], pipeout[2], pipeerr[2];
|
int pipein[2], pipeout[2], pipeerr[2];
|
||||||
if ( !handler_set){
|
setHandler();
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (fdin && *fdin == -1 && pipe(pipein) < 0){
|
if (fdin && *fdin == -1 && pipe(pipein) < 0){
|
||||||
#if DEBUG >= 1
|
#if DEBUG >= 1
|
||||||
std::cerr << "Pipe (in) creation failed for " << name << std::endl;
|
std::cerr << "Pipe (in) creation failed for " << name << std::endl;
|
||||||
|
|
|
@ -18,7 +18,9 @@ namespace Util {
|
||||||
static std::map<pid_t, TerminationNotifier> exitHandlers; ///< termination function, if any
|
static std::map<pid_t, TerminationNotifier> exitHandlers; ///< termination function, if any
|
||||||
static bool handler_set; ///< If true, the sigchld handler has been setup.
|
static bool handler_set; ///< If true, the sigchld handler has been setup.
|
||||||
static void childsig_handler(int signum);
|
static void childsig_handler(int signum);
|
||||||
|
static void exit_handler();
|
||||||
static void runCmd(std::string & cmd);
|
static void runCmd(std::string & cmd);
|
||||||
|
static void setHandler();
|
||||||
public:
|
public:
|
||||||
static pid_t Start(std::string name, std::string cmd);
|
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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue