class ProcessGroup
A group of processes that are all killed when the group is closed.
Definitions
def self.spawn(*arguments)
Spawn a new process group with a given command.
Signature
-
parameter
arguments
Array
The command to execute.
Implementation
def self.spawn(*arguments)
# This might be problematic...
self.new(
::Process.spawn(*arguments, pgroup: true, out: File::NULL, err: File::NULL)
)
end
def initialize(pid)
Create a new process group from an existing process id.
Signature
-
parameter
pid
Integer
The process id.
Implementation
def initialize(pid)
@pid = pid
@status_task = Async(transient: true) do
@status = ::Process.wait(@pid)
unless @status.success?
Console.error(self, "Process exited unexpectedly: #{@status}")
end
ensure
self.close
end
end
def close
Close the process group.
Implementation
def close
if @status_task
@status_task.stop
@status_task = nil
end
if @pid
::Process.kill("INT", -@pid)
Async do |task|
task.with_timeout(1) do
::Process.wait(@pid)
rescue Errno::ECHILD
# Done.
rescue Async::TimeoutError
Console.info(self, "Killing pid #{@pid}...")
::Process.kill("KILL", -@pid)
end
end.wait
wait_all(-@pid)
@pid = nil
end
end
def wait_all(pgid)
Wait for all processes in the group to exit.
Implementation
def wait_all(pgid)
while true
pid, status = ::Process.wait2(pgid, ::Process::WNOHANG)
break unless pid
end
rescue Errno::ECHILD
# Done.
end