Recursively Kill R Process with Children in Linux

Recursively kill R process with children in linux

This is mainly about the multicore part. Children are waiting for you to collect the results - see ?collect. Normally, you should never use parallel without a provision to clean up, typically in on.exit. multicore cleans up in high-level functions like mclapply, but if you use lower-level functions it is your responsibility to perform the cleanup (since multicore cannot know if you left the children running intentionally or not).

Your example is really bogus, because you don't even consider collecting results. But anyway, if that is really what you want, you'll have to do the cleanup at some point. For example, if you want to terminate all children on exit, you could define .Last like this:

 .Last <- function(...) {
collect(wait=FALSE)
all <- children()
if (length(all)) {
kill(all, SIGTERM)
collect(all)
}
}

Again, the above is not a recommended way to deal with this - it rather a last resort. You should really assign jobs and collect results like

jobs <- lapply(1:3, function(i) parallel({Sys.sleep(i); i}))
collect(jobs)

As for the general process child question - init inherits the children only after R quits, but in .Last you can still find their pids since the parent process exists at that point so you could perform similar cleanup as in the multicore case.

What's the best way to send a signal to all members of a process group?

You don't say if the tree you want to kill is a single process group. (This is often the case if the tree is the result of forking from a server start or a shell command line.) You can discover process groups using GNU ps as follows:

 ps x -o  "%p %r %y %x %c "

If it is a process group you want to kill, just use the kill(1) command but instead of giving it a process number, give it the negation of the group number. For example to kill every process in group 5112, use kill -TERM -- -5112.

How to kill a child process after a given timeout in Bash?

(As seen in:
BASH FAQ entry #68: "How do I run a command, and have it abort (timeout) after N seconds?")

If you don't mind downloading something, use timeout (sudo apt-get install timeout) and use it like: (most Systems have it already installed otherwise use sudo apt-get install coreutils)

timeout 10 ping www.goooooogle.com

If you don't want to download something, do what timeout does internally:

( cmdpid=$BASHPID; (sleep 10; kill $cmdpid) & exec ping www.goooooogle.com )

In case that you want to do a timeout for longer bash code, use the second option as such:

( cmdpid=$BASHPID; 
(sleep 10; kill $cmdpid) \
& while ! ping -w 1 www.goooooogle.com
do
echo crap;
done )

How a child process kill other child process and then terminate?

Besides the issue of uninitialized buf identified by @G. Sliepen, the pipe() need be called before fork() as file descriptors are kept open when forking child process(s). This is also how pipe works.

You can try to change your code snippet to put pipe() before fork().

...
if (pipe(fd) == -1)
{
perror(" pipe ");
exit(1);
}
pid = fork();
if (pid < 0)
{
perror("fork");
exit(1);
}
...

Please read the manual page of pipe(2) in which an example presented.

SO has this post fork() and pipes() in c explained this as well.

Update for terminating process(s)

This child process has no knowledge about existence of its siblings, but its parent process has. If not explicitly required, you can let the parent to do so, i.e. to "end" all child processes.

BTW, instead of sending signal SIGUSR1 it is better to send SIGTERM signal. Although SIGUSSR1 can cause the target process be terminated by default (see signal(7)).

To "finish", i.e. to kill (or terminate) all the child processes as well as parent process, you can simplly kill the parent. All its descendants got killed as well. Or, you can send signal to the same process group. See kill(2).

How to kill all processes with a given partial name?

Use pkill -f, which matches the pattern for any part of the command line

pkill -f my_pattern

Just in case it doesn't work, try to use this one as well:

pkill -9 -f my_pattern

How to kill all subprocesses of shell?

After starting each child process, you can get its id with

ID=$!

Then you can use the stored PIDs to find and kill all grandchild etc. processes as described here or here.

Identify a process started in VB.Net to be able to kill it and all its children later

Based on the C# code given as part of an answer to Find all child processes of my own .NET process, I used the following code that seem to work to kill all children of a process knowing its PID :

Sub killChildrenProcessesOf(ByVal parentProcessId As UInt32)
Dim searcher As New ManagementObjectSearcher(
"SELECT * " &
"FROM Win32_Process " &
"WHERE ParentProcessId=" & parentProcessId)

Dim Collection As ManagementObjectCollection
Collection = searcher.Get()

If (Collection.Count > 0) Then

consoleDisplay("Killing " & Collection.Count & " processes started by process with Id """ & parentProcessId & """.")
For Each item In Collection
Dim childProcessId As Int32
childProcessId = Convert.ToInt32(item("ProcessId"))
If Not (childProcessId = Process.GetCurrentProcess().Id) Then

killChildrenProcessesOf(childProcessId)

Dim childProcess As Process
childProcess = Process.GetProcessById(childProcessId)
consoleDisplay("Killing child process """ & childProcess.ProcessName & """ with Id """ & childProcessId & """.")
childProcess.Kill()
End If
Next
End If
End Sub

For information, it is needed to :

Imports System.Management

Then if you use Visual Studio, you'll need to go under the project menu, select "Add Reference...", under the ".Net" tab, scroll down to "System.Management" and select the line corresponding to "System.Management" and click OK. (as stated in this answer)

When correctly called, this Sub is satisfying to kill all children started by a parent process. If need, a basic parentProcess.kill kill the parent process.

cleanup when a R script is killed

The .Last function needs to be defined before we can send the interrupt to R. So it should be:

print("script called")

.Last<-function()
{
print("Last called")
}

Sys.sleep(20)

It works fine now.

How do I kill background processes / jobs when my shell script exits?

To clean up some mess, trap can be used. It can provide a list of stuff executed when a specific signal arrives:

trap "echo hello" SIGINT

but can also be used to execute something if the shell exits:

trap "killall background" EXIT

It's a builtin, so help trap will give you information (works with bash). If you only want to kill background jobs, you can do

trap 'kill $(jobs -p)' EXIT

Watch out to use single ', to prevent the shell from substituting the $() immediately.



Related Topics



Leave a reply



Submit