Fixed slow process exit bug, improved debug messaging for procs.
This commit is contained in:
parent
5c0f053006
commit
0fe0c1fb4f
1 changed files with 51 additions and 25 deletions
|
@ -25,6 +25,16 @@ 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;
|
||||||
|
|
||||||
|
static bool childRunning(pid_t p){
|
||||||
|
pid_t ret = waitpid(p, 0, WNOHANG);
|
||||||
|
if (ret == p){return false;}
|
||||||
|
if (ret < 0 && errno == EINTR){
|
||||||
|
return childRunning(p);
|
||||||
|
}
|
||||||
|
if (kill(p, 0) == 0){return true;}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// Called at exit of any program that used a Start* function.
|
/// Called at exit of any program that used a Start* function.
|
||||||
/// Waits up to 1 second, then sends SIGINT signal to all managed processes.
|
/// Waits up to 1 second, then sends SIGINT signal to all managed processes.
|
||||||
/// After that waits up to 5 seconds for children to exit, then sends SIGKILL to
|
/// After that waits up to 5 seconds for children to exit, then sends SIGKILL to
|
||||||
|
@ -33,61 +43,75 @@ void Util::Procs::exit_handler(){
|
||||||
int waiting = 0;
|
int waiting = 0;
|
||||||
std::map<pid_t, std::string> listcopy = plist;
|
std::map<pid_t, std::string> listcopy = plist;
|
||||||
std::map<pid_t, std::string>::iterator it;
|
std::map<pid_t, std::string>::iterator it;
|
||||||
|
if (listcopy.empty()){return;}
|
||||||
|
|
||||||
//wait up to 1 second for applications to shut down
|
//wait up to 0.5 second for applications to shut down
|
||||||
while ( !listcopy.empty() && waiting <= 50){
|
while ( !listcopy.empty() && waiting <= 25){
|
||||||
for (it = listcopy.begin(); it != listcopy.end(); it++){
|
for (it = listcopy.begin(); it != listcopy.end(); it++){
|
||||||
if (kill(( *it).first, 0) == 0){
|
if ( !childRunning((*it).first)){
|
||||||
Util::sleep(20);
|
|
||||||
++waiting;
|
|
||||||
}else{
|
|
||||||
listcopy.erase(it);
|
listcopy.erase(it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if ( !listcopy.empty()){
|
||||||
|
Util::sleep(20);
|
||||||
|
++waiting;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (listcopy.empty()){return;}
|
||||||
|
|
||||||
|
DEBUG_MSG(DLVL_DEVEL, "Sending SIGINT to remaining %d children", (int)listcopy.size());
|
||||||
//send sigint to all remaining
|
//send sigint to all remaining
|
||||||
if ( !listcopy.empty()){
|
if ( !listcopy.empty()){
|
||||||
for (it = listcopy.begin(); it != listcopy.end(); it++){
|
for (it = listcopy.begin(); it != listcopy.end(); it++){
|
||||||
|
DEBUG_MSG(DLVL_DEVEL, "SIGINT %d: %s", ( *it).first, ( *it).second.c_str());
|
||||||
kill(( *it).first, SIGINT);
|
kill(( *it).first, SIGINT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG_MSG(DLVL_DEVEL, "Waiting up to 5 seconds for %d children to terminate.", (int)listcopy.size());
|
||||||
waiting = 0;
|
waiting = 0;
|
||||||
//wait up to 5 seconds for applications to shut down
|
//wait up to 5 seconds for applications to shut down
|
||||||
while ( !listcopy.empty() && waiting <= 50){
|
while ( !listcopy.empty() && waiting <= 250){
|
||||||
for (it = listcopy.begin(); it != listcopy.end(); it++){
|
for (it = listcopy.begin(); it != listcopy.end(); it++){
|
||||||
if (kill(( *it).first, 0) == 0){
|
if ( !childRunning((*it).first)){
|
||||||
Util::sleep(100);
|
|
||||||
++waiting;
|
|
||||||
}else{
|
|
||||||
listcopy.erase(it);
|
listcopy.erase(it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if ( !listcopy.empty()){
|
||||||
|
Util::sleep(20);
|
||||||
|
++waiting;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (listcopy.empty()){return;}
|
||||||
|
|
||||||
|
DEBUG_MSG(DLVL_DEVEL, "Sending SIGKILL to remaining %d children", (int)listcopy.size());
|
||||||
//send sigkill to all remaining
|
//send sigkill to all remaining
|
||||||
if ( !plist.empty()){
|
if ( !listcopy.empty()){
|
||||||
for (it = listcopy.begin(); it != listcopy.end(); it++){
|
for (it = listcopy.begin(); it != listcopy.end(); it++){
|
||||||
|
DEBUG_MSG(DLVL_DEVEL, "SIGKILL %d: %s", ( *it).first, ( *it).second.c_str());
|
||||||
kill(( *it).first, SIGKILL);
|
kill(( *it).first, SIGKILL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG_MSG(DLVL_DEVEL, "Waiting up to a second for %d children to terminate.", (int)listcopy.size());
|
||||||
waiting = 0;
|
waiting = 0;
|
||||||
//wait up to 1 second for applications to shut down
|
//wait up to 1 second for applications to shut down
|
||||||
while ( !listcopy.empty() && waiting <= 50){
|
while ( !listcopy.empty() && waiting <= 50){
|
||||||
for (it = listcopy.begin(); it != listcopy.end(); it++){
|
for (it = listcopy.begin(); it != listcopy.end(); it++){
|
||||||
if (kill(( *it).first, 0) == 0){
|
if ( !childRunning((*it).first)){
|
||||||
Util::sleep(20);
|
|
||||||
++waiting;
|
|
||||||
}else{
|
|
||||||
listcopy.erase(it);
|
listcopy.erase(it);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if ( !listcopy.empty()){
|
||||||
|
Util::sleep(20);
|
||||||
|
++waiting;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (listcopy.empty()){return;}
|
||||||
|
DEBUG_MSG(DLVL_DEVEL, "Giving up with %d children left.", (int)listcopy.size());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,13 +152,15 @@ void Util::Procs::childsig_handler(int signum){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG >= DLVL_DEVEL
|
#if DEBUG >= DLVL_HIGH
|
||||||
std::string pname = plist[ret];
|
std::string pname = plist[ret];
|
||||||
#endif
|
#endif
|
||||||
plist.erase(ret);
|
plist.erase(ret);
|
||||||
#if DEBUG >= DLVL_DEVEL
|
#if DEBUG >= DLVL_HIGH
|
||||||
if (!isActive(pname)){
|
if (!isActive(pname)){
|
||||||
DEBUG_MSG(DLVL_DEVEL, "Process %s fully terminated", pname.c_str());
|
DEBUG_MSG(DLVL_HIGH, "Process %s fully terminated", pname.c_str());
|
||||||
|
}else{
|
||||||
|
DEBUG_MSG(DLVL_HIGH, "Child process %d exited", ret);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -221,7 +247,7 @@ pid_t Util::Procs::Start(std::string name, std::string cmd){
|
||||||
runCmd(cmd);
|
runCmd(cmd);
|
||||||
}else{
|
}else{
|
||||||
if (ret > 0){
|
if (ret > 0){
|
||||||
DEBUG_MSG(DLVL_DEVEL, "Process %s started, PID %d: %s", name.c_str(), ret, cmd.c_str());
|
DEBUG_MSG(DLVL_HIGH, "Process %s started, PID %d: %s", name.c_str(), ret, cmd.c_str());
|
||||||
plist.insert(std::pair<pid_t, std::string>(ret, name));
|
plist.insert(std::pair<pid_t, std::string>(ret, name));
|
||||||
}else{
|
}else{
|
||||||
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started: fork() failed", name.c_str());
|
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started: fork() failed", name.c_str());
|
||||||
|
@ -277,7 +303,7 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2){
|
||||||
runCmd(cmd2);
|
runCmd(cmd2);
|
||||||
}else{
|
}else{
|
||||||
if (ret2 > 0){
|
if (ret2 > 0){
|
||||||
DEBUG_MSG(DLVL_DEVEL, "Process %s started, PIDs (%d, %d): %s | %s", name.c_str(), ret, ret2, cmd.c_str(), cmd2.c_str());
|
DEBUG_MSG(DLVL_HIGH, "Process %s started, PIDs (%d, %d): %s | %s", name.c_str(), ret, ret2, cmd.c_str(), cmd2.c_str());
|
||||||
plist.insert(std::pair<pid_t, std::string>(ret2, name));
|
plist.insert(std::pair<pid_t, std::string>(ret2, name));
|
||||||
}else{
|
}else{
|
||||||
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
|
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
|
||||||
|
@ -350,7 +376,7 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, st
|
||||||
runCmd(cmd2);
|
runCmd(cmd2);
|
||||||
}else{
|
}else{
|
||||||
if (ret2 > 0){
|
if (ret2 > 0){
|
||||||
DEBUG_MSG(DLVL_DEVEL, "Process %s started, PIDs (%d, %d): %s | %s", name.c_str(), ret, ret2, cmd.c_str(), cmd2.c_str());
|
DEBUG_MSG(DLVL_HIGH, "Process %s started, PIDs (%d, %d): %s | %s", name.c_str(), ret, ret2, cmd.c_str(), cmd2.c_str());
|
||||||
plist.insert(std::pair<pid_t, std::string>(ret2, name));
|
plist.insert(std::pair<pid_t, std::string>(ret2, name));
|
||||||
}else{
|
}else{
|
||||||
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
|
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
|
||||||
|
@ -377,7 +403,7 @@ pid_t Util::Procs::Start(std::string name, std::string cmd, std::string cmd2, st
|
||||||
runCmd(cmd3);
|
runCmd(cmd3);
|
||||||
}else{
|
}else{
|
||||||
if (ret3 > 0){
|
if (ret3 > 0){
|
||||||
DEBUG_MSG(DLVL_DEVEL, "Process %s started, PIDs (%d, %d, %d): %s | %s | %s", name.c_str(), ret, ret2, ret3, cmd.c_str(), cmd2.c_str(), cmd3.c_str());
|
DEBUG_MSG(DLVL_HIGH, "Process %s started, PIDs (%d, %d, %d): %s | %s | %s", name.c_str(), ret, ret2, ret3, cmd.c_str(), cmd2.c_str(), cmd3.c_str());
|
||||||
plist.insert(std::pair<pid_t, std::string>(ret3, name));
|
plist.insert(std::pair<pid_t, std::string>(ret3, name));
|
||||||
}else{
|
}else{
|
||||||
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
|
DEBUG_MSG(DLVL_ERROR, "Process %s could not be started. fork() failed.", name.c_str());
|
||||||
|
@ -509,7 +535,7 @@ pid_t Util::Procs::StartPiped(std::string name, char* const* argv, int * fdin, i
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}else{ //parent
|
}else{ //parent
|
||||||
DEBUG_MSG(DLVL_DEVEL, "Piped process %s started, PID %d: %s", name.c_str(), pid, argv[0]);
|
DEBUG_MSG(DLVL_HIGH, "Piped process %s started, PID %d: %s", name.c_str(), pid, argv[0]);
|
||||||
if (devnull != -1){
|
if (devnull != -1){
|
||||||
close(devnull);
|
close(devnull);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue