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

View File

@ -53,6 +53,7 @@ do.
#include <errno.h> /* errno */
#include <time.h> /* gettimeofday */
#include <signal.h> /* sigaction */
#include <dirent.h> /* DIR, dirent */
/* 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
@ -98,6 +99,7 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProc
static void kwsysProcessSetExitException(kwsysProcess* cp, int sig);
static void kwsysProcessChildErrorExit(int errorPipe);
static void kwsysProcessRestoreDefaultSignalHandlers(void);
static void kwsysProcessKill(pid_t process_id);
/*--------------------------------------------------------------------------*/
/* Structure containing data used to implement the child's execution. */
@ -992,7 +994,7 @@ void kwsysProcess_Kill(kwsysProcess* cp)
{
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])
{
kill(cp->ForkPIDs[i], SIGKILL);
kwsysProcessKill(cp->ForkPIDs[i]);
}
}
}
@ -1716,3 +1718,73 @@ static void kwsysProcessRestoreDefaultSignalHandlers(void)
sigaction(SIGUNUSED, &act, 0);
#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);
}