Skip to content

Instantly share code, notes, and snippets.

@olbat
Last active October 21, 2017 07:29
Show Gist options
  • Save olbat/f9f4c21a2f0ebb9479f2a5fc52b5d66e to your computer and use it in GitHub Desktop.
Save olbat/f9f4c21a2f0ebb9479f2a5fc52b5d66e to your computer and use it in GitHub Desktop.
Ruby recursive Process.kill
module Process::KillRecursive
refine Process.singleton_class do
def children(pid)
pids = nil
if RbConfig::CONFIG['host_os'] =~ /linux/i
if File.exist?("/proc/#{pid}/task/#{pid}/children")
pids = File.read("/proc/#{pid}/task/#{pid}/children").split(/\s/)
end
elsif !Gem.win_platform?
pids = `ps --ppid #{pid} -o pid=`.split("\n")
raise NotImplementedError unless $?.success?
else
raise NotImplementedError
end
pids.tap{|ps| ps.map!{|p| p.strip.to_i }.uniq! }
end
def kill_recursive(pid)
# SIGSTOPs the process to avoid it creating new children
begin
Process.kill('STOP', pid)
rescue Errno::ESRCH # The process was already killed
return
end
# Gather the list of children before killing the parent (after the kill
# children are re-attached to init and impossible to find)
children = children(pid)
# TODO: check if this do not generate <defunct> children
# if it does, kill the process before it's children
children.each do |cpid|
kill_recursive(cpid)
end if children
begin
Process.kill('KILL', pid)
rescue Errno::ESRCH # The process was already killed
return
end
end
end
end
=begin
class SomeClass
using Process::KillRecursive
def some_method(pid)
Process.kill_recursive(pid)
end
end
=end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment