首页 > 解决方案 > 为什么在信号陷阱块中杀死的进程会变成僵尸而不是定期终止?

问题描述

如果我使用 创建进程Process.new,它们可以被杀死.kill。然而,他们在信号陷阱中变成了僵尸:

PROCESSES = {} of Int32 => Process

spawn {
  loop { sleep 1 }
}

spawn {
  x = Process.new("sleep", "100".split)
  x.kill
  sleep 0.4
  puts x.terminated?

  x = Process.new("sleep", "100".split)
  PROCESSES[x.pid] = x
}


Signal::INT.trap {
  Signal::INT.reset
  PROCESSES.each { |pid, x|
    puts "killing: #{pid}"
    x.kill
    sleep 1
    puts "killed #{pid}? #{x.terminated?}"
  }
}
sleep

运行此代码crystal run并向进程发送 SIGINT 将始终.terminated?为该进程返回 true,因为它处于僵尸 ( <defunct>) 状态。

标签: crystal-lang

解决方案


当它们的父进程不收集它们的状态时,即当它不调用任何wait函数族时,进程就会变成僵尸。

对于您的示例,您应该保留Process实例并Process#wait在发送终止信号后调用。如果您想同时为多个进程执行此操作,只需将每个调用都waitspawn.


推荐阅读