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 <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);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue