BUG#392: Implementation of process tree killing for systems with /proc filesystem.

This commit is contained in:
Brad King 2004-07-02 16:39:29 -04:00
parent 0b7ab2a4aa
commit e6145d6878
1 changed files with 74 additions and 2 deletions

View File

@ -53,6 +53,7 @@ do.
#include <errno.h> /* errno */ #include <errno.h> /* errno */
#include <time.h> /* gettimeofday */ #include <time.h> /* gettimeofday */
#include <signal.h> /* sigaction */ #include <signal.h> /* sigaction */
#include <dirent.h> /* DIR, dirent */
/* The number of pipes for the child's output. The standard stdout /* The number of pipes for the child's output. The standard stdout
and stderr pipes are the first two. One more pipe is used to and stderr pipes are the first two. One more pipe is used to
@ -98,6 +99,7 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProc
static void kwsysProcessSetExitException(kwsysProcess* cp, int sig); static void kwsysProcessSetExitException(kwsysProcess* cp, int sig);
static void kwsysProcessChildErrorExit(int errorPipe); static void kwsysProcessChildErrorExit(int errorPipe);
static void kwsysProcessRestoreDefaultSignalHandlers(void); static void kwsysProcessRestoreDefaultSignalHandlers(void);
static void kwsysProcessKill(pid_t process_id);
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/* Structure containing data used to implement the child's execution. */ /* Structure containing data used to implement the child's execution. */
@ -992,7 +994,7 @@ void kwsysProcess_Kill(kwsysProcess* cp)
{ {
if(cp->ForkPIDs[i]) if(cp->ForkPIDs[i])
{ {
kill(cp->ForkPIDs[i], SIGKILL); kwsysProcessKill(cp->ForkPIDs[i]);
} }
} }
} }
@ -1090,7 +1092,7 @@ static void kwsysProcessCleanup(kwsysProcess* cp, int error)
{ {
if(cp->ForkPIDs[i]) if(cp->ForkPIDs[i])
{ {
kill(cp->ForkPIDs[i], SIGKILL); kwsysProcessKill(cp->ForkPIDs[i]);
} }
} }
} }
@ -1716,3 +1718,73 @@ static void kwsysProcessRestoreDefaultSignalHandlers(void)
sigaction(SIGUNUSED, &act, 0); sigaction(SIGUNUSED, &act, 0);
#endif #endif
} }
/*--------------------------------------------------------------------------*/
static void kwsysProcessKill(pid_t process_id)
{
DIR* procdir;
/* Suspend the process to be sure it will not create more children. */
kill(process_id, SIGSTOP);
/* Kill all children if we can find them. Currently this works only
on systems that support the proc filesystem. */
if((procdir = opendir("/proc")) != NULL)
{
#if defined(MAXPATHLEN)
char fname[MAXPATHLEN];
#elif defined(PATH_MAX)
char fname[PATH_MAX];
#else
char fname[4096];
#endif
const int bufferSize = 1024;
char buffer[bufferSize+1];
struct dirent* d;
/* Each process has a directory in /proc whose name is the pid.
Within this directory is a file called stat that has the
following format:
pid (command line) status ppid ...
We want to get the ppid for all processes. Those that have
process_id as their parent should be recursively killed. */
for(d = readdir(procdir); d; d = readdir(procdir))
{
int pid;
if(sscanf(d->d_name, "%d", &pid) == 1 && pid != 0)
{
struct stat finfo;
sprintf(fname, "/proc/%d/stat", pid);
if(stat(fname, &finfo) == 0)
{
FILE* f = fopen(fname, "r");
if(f)
{
int nread = fread(buffer, 1, bufferSize, f);
buffer[nread] = '\0';
if(nread > 0)
{
const char* rparen = strrchr(buffer, ')');
int ppid;
if(rparen && (sscanf(rparen+1, "%*s %d", &ppid) == 1))
{
if(ppid == process_id)
{
/* Recursively kill this child and its children. */
kwsysProcessKill(pid);
}
}
}
fclose(f);
}
}
}
}
closedir(procdir);
}
/* Kill the process. */
kill(process_id, SIGKILL);
}