如何终止子进程作为终止创建它的线程的一部分

时间:2017-04-26 12:32:31

标签: ruby multithreading child-process

我有一个Ruby应用程序,它按需生成一个线程,然后进行系统调用以执行本机二进制文件。

我想在本机调用完成之前中止此调用。

我尝试使用Thread文档提供的所有选项,例如killraiseterminate,但似乎没有任何帮助。

这就是我要做的事情:

class Myserver < Grape::API
@@thr = nil

  post "/start" do
    puts "Starting script"
    @@thr = Thread.new do
     op=`sh chumma_sh.sh`
     puts op
    end
    puts @@thr.status
  end

  put "/stop" do
    @@thr.terminate
    @@thr.raise
    Thread.kill(@@thr)
    puts @@thr.status
  end
end

当IO操作正在进行时,线程似乎进入睡眠状态,但是如何终止该线程以便它创建的所有子进程都终止并且不会附加到root。

为脚本执行ps-ef | grep会返回pid,我可以尝试Process.kill pid,但想知道是否有更好的选项。

此时我没有修改脚本执行方式的选项,因为它是继承库的一部分。

1 个答案:

答案 0 :(得分:0)

使用ps是我发现有效的唯一方法。如果你还想杀死子线程,你可以使用这样的东西:

def child_pids_recursive(pid)
  # get children
  pipe = IO.popen("ps -ef | grep #{pid}")

  child_pids = pipe.readlines.map do |line|
    parts = line.split(/\s+/)
    parts[2] if parts[3] == pid.to_s && parts[2] != pipe.pid.to_s
  end.compact

  pipe.close

  # get grandchildren
  grandchild_pids = child_pids.map do |cpid|
    child_pids_recursive(cpid)
  end.flatten

  child_pids + grandchild_pids
end

def kill_all(pid)
  child_pids_recursive(pid).reverse.each do |p|
    begin
      Process.kill('TERM', p.to_i)
    rescue
      # ignore
    end
  end
end