diff options
author | Brad King <brad.king@kitware.com> | 2004-07-02 20:39:29 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2004-07-02 20:39:29 (GMT) |
commit | e6145d6878d0733d9ec39a2690a5fd7e4978ebd8 (patch) | |
tree | 391349c90b9cd4086444583cd037839ead176b47 /Source/kwsys/ProcessUNIX.c | |
parent | 0b7ab2a4aab13abc0fb223a0ce41dacb67fa870b (diff) | |
download | CMake-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.c | 76 |
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); +} |