BUG#392: Implementation of process tree killing for systems with /proc filesystem.
This commit is contained in:
parent
0b7ab2a4aa
commit
e6145d6878
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue