summaryrefslogtreecommitdiffstats
path: root/Source/kwsys/ProcessUNIX.c
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2004-07-02 20:39:29 (GMT)
committerBrad King <brad.king@kitware.com>2004-07-02 20:39:29 (GMT)
commite6145d6878d0733d9ec39a2690a5fd7e4978ebd8 (patch)
tree391349c90b9cd4086444583cd037839ead176b47 /Source/kwsys/ProcessUNIX.c
parent0b7ab2a4aab13abc0fb223a0ce41dacb67fa870b (diff)
downloadCMake-e6145d6878d0733d9ec39a2690a5fd7e4978ebd8.zip
CMake-e6145d6878d0733d9ec39a2690a5fd7e4978ebd8.tar.gz
CMake-e6145d6878d0733d9ec39a2690a5fd7e4978ebd8.tar.bz2
BUG#392: Implementation of process tree killing for systems with /proc filesystem.
Diffstat (limited to 'Source/kwsys/ProcessUNIX.c')
-rw-r--r--Source/kwsys/ProcessUNIX.c76
1 files changed, 74 insertions, 2 deletions
diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c
index b5c1e19..d05213c 100644
--- a/Source/kwsys/ProcessUNIX.c
+++ b/Source/kwsys/ProcessUNIX.c
@@ -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);
+}