tags:

views:

3856

answers:

5

We have a c++ task that will fork a new process. That process in turn may have several child processes. If the task runs past an allotted time, we will want to kill that forked process. However, we don't want to orphan the processes it has spawned. We want them all to die. I have used Process Explorer and it has a "Kill Process Tree" option, similar to Windows Task Manager's "End Process Tree", so I'm guessing/assuming there is a public API to do this. Has anyone done this, or know of a reference to a public API that does?

Thx, Brett

+7  A: 

You might want to consider the "Jobs API". CreateJobObject and friends. You can enforce children processes to stay within the Job, by setting appropriate attribute. Then you can call TerminateJobObject whenever you want.

Clarification: this is NOT what Task Manager does.

EFraim
follow up, if that forked process dies and orphans its jobs, will TerminateJobObject still be able to kill the orphans left behind?
Brett McCann
Yes, see relevant API doc. Unless a process was created with CREATE_BREAKAWAY_FROM_JOB flag.
EFraim
Though running away is not possible if JOB_OBJECT_LIMIT_BREAKAWAY_OK limit in the job object is not set.
EFraim
I'd vote this up twice if I could. The application in the question is *exactly* what the Job object was designed for.
Greg Hewgill
Beware of trouble with Vista's Explorer.exe. I've seen it put processes started through a shortcut in a job, preventing creating your own job.
Hans Passant
+3  A: 

There is a Win32 function called TerminateProcess(). It should do the job for you.

Alternatively, I've found the taskkill command to be useful for things like this.

from the command line:

taskkill /F /T /IM program.exe

from code:

system("taskkill /F /T /IM program.exe");

other switches (straight from taskkill /? ):

 TASKKILL [/S system [/U username [/P
 [password]]]]
          { [/FI filter] [/PID processid | /IM imagename] } [/F] [/T]

 Description:
     This command line tool can be used to end one or more processes.
     Processes can be killed by the process id or image name.

 Parameter List:
     /S    system           Specifies the remote system to connect to.

     /U    [domain\]user    Specifies the user context under which
                            the command should execute.

     /P    [password]       Specifies the password for the given
                            user context. Prompts for input if omitted.

     /F                     Specifies to forcefully terminate
                            process(es).

     /FI   filter           Displays a set of tasks that match a
                            given criteria specified by the filter.

     /PID  process id       Specifies the PID of the process that
                            has to be terminated.

     /IM   image name       Specifies the image name of the process
                            that has to be terminated. Wildcard '*'
                            can be used to specify all image names.

     /T                     Tree kill: terminates the specified process
                            and any child processes which were started by it.

     /?                     Displays this help/usage.

-John

John T
+1  A: 

You want to find the process id for the process you want to kill, then "walk the tree" of its children (and their children, and so on...), note their pids, and then kill all the processes nice and quickly.

James Caccese
+3  A: 

I suggest going the job object route, as indicated above, it will be the most reliable. If you can't go the job object route, you can use the toolhelp API to get parent process ID's and build the tree that way. Be cautious though, since Windows doesn't have a strong parent/child relationship and it is possible for PID's to get recycled. You can use GetProcessTimes to query the creation time of the process, and check that it is older than the child. If an intermediate process in the tree is terminated, you will not be able to walk the tree further.

// Error handling removed for brevity
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 process;
ZeroMemory(&process, sizeof(process));
process.dwSize = sizeof(process);
Process32First(snapshot, &process);
do
{
    // process.th32ProcessId is the PID.
    // process.th32ParentProcessID is the parent PID.

 } while (Process32Next(snapshot, &process));
Michael
Yes, this is what you'll need to use on Vista.
Hans Passant
A: 

You can also use WMI, route planning you can create a class to perform the tasks.
Se this "Where can I find the WMI documentation?"
and The WMI COM library
and WMI C++ Application Examples

lsalamon