我有一些情况需要在一段时间后杀死进程。我开始这个过程然后
case <-time.After(timeout):
if err := cmd.Process.Kill(); err != nil {
return 0, fmt.Errorf("Failed to kill process: %v", err)
}
杀死了这个过程。但它只会杀死父进程而不是主进程启动的5-10子进程。我还尝试创建一个进程组然后执行
syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
杀死主进程和孙进程,但不能正常工作。还有其他方法可以杀死这些进程。
答案 0 :(得分:2)
我认为这就是你所需要的:
cmd := exec.Command(command, arguments...)
// This sets up a process group which we kill later.
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
if err := cmd.Start(); err != nil {
return err
}
// buffered chan is important so the goroutine does't
// get blocked and stick around if the function returns
// after the timeout
done := make(chan error, 1)
go func() {
done <- cmd.Wait()
}()
select {
case err := <-done:
// this will be nil if no error
return err
case <-time.After(time.Second):
// We created a process group above which we kill here.
pgid, err := syscall.Getpgid(cmd.Process.Pid)
if err != nil {
return err
}
// note the minus sign
if err := syscall.Kill(-pgid, 15); err != nil {
return err
}
return fmt.Errorf("Timeout")
}
答案 1 :(得分:0)
尚不清楚您是否可以控制这些子进程。如果是这样,您可以考虑使用以下Linux功能(您也不必说它是否特定于操作系统)。
这行代码要求内核在父母去世时向孩子发送SIGHUP。这样,您的Go进程就可以杀死父进程,并自动杀死所有子进程。不仅如此,它永远不会失败!内核真的很不错。
def check_auth(id_token):
decoded_token = auth.verify_id_token(id_token)
uid = decoded_token['uid']
print(uid)
return uid
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.headers.get("Authorization")
if not auth or not check_auth(auth):
message = {"error": "Authorization Required"}
resp = message
return resp
return f(*args, **kwargs)
return decorated
当然,如果您这样做的话,就有竞争条件。也就是说,当孩子调用此prctl(PR_SET_PDEATHSIG, SIGHUP);
函数时,父母可能已经死亡,在这种情况下,孩子需要立即退出。
prctl()
因此避免竞争情况的完整代码是:
if(getppid() != parent_pid)
{
exit(1);
}
注意:在这种情况下,习惯上使用// must happen before the fork() call
const pid_t parent_pid = getpid();
const pid_t child_pid = fork();
if(child_pid != 0)
{
// fork() failed (child_pid == -1) or worked (an actual PID)
...
return;
}
prctl(PR_SET_PDEATHSIG, SIGHUP);
if(getppid() != parent_pid)
{
exit(1);
}
。您可能还需要考虑其他信号,特别是如果孩子处理管道/插座(在这种情况下,您可能会忽略SIGHUP
!)或出于其他原因而需要处理SIGHUP
。
现在,如果您对子进程的代码没有任何控制……您可以尝试通过搜索所有子进程,逐一杀死它们,然后杀死父进程,从Go应用程序中杀死每个进程。但是,除非您无法阻止整个孩子树创建新流程,否则您总是会遇到无法避免的竞争条件。如果可以的话,只需注册所有这些孩子的PID并逐个杀死它们。
当然,如果您可以创建一个小组,那就更好了。像上面的SIGHUP一样,杀死组的所有成员都是由内核完成的,并且不会丢失任何进程。