为什么不正确地终止子进程? [英] Why won't Go kill a child process correctly?

查看:121
本文介绍了为什么不正确地终止子进程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当cmd在指定的时间内完成时,以下工作正常.但是,超时不起作用.尽管确实打印"It's dead Jim",但它不仅无法打印"Done waiting",而且实际上并未终止该进程.它继续运行,并且"Done waiting"从不打印.

The following works just fine when cmd finishes in the allotted time. However, the timeout is not working. While it does print "It's dead Jim", not only does it fail to print "Done waiting", but the process is not actually killed. It continues to run, and "Done waiting" never prints.

我认为这是所有相关的代码,但是我对Go还是很陌生(这是我尝试过的第一个实际项目),所以如果还不够的话,请告诉我.

I think this is all of the relevant code, but I'm very new to Go (this is the first real project I've attempted with it) so if this isn't enough let me know.

func() {
    var output bytes.Buffer
    cmd := exec.Command("Command", args...)
    cmd.Dir = filepath.Dir(srcFile)
    cmd.Stdout, cmd.Stderr = &output, &output
    if err := cmd.Start(); err != nil {
        return err
    }
    defer time.AfterFunc(time.Second*2, func() {
        fmt.Printf("Nobody got time fo that\n")
        if err := cmd.Process.Signal(syscall.SIGKILL); err != nil {
            fmt.Printf("Error:%s\n", err)
        }
        fmt.Printf("It's dead Jim\n")
    }).Stop()
    err := cmd.Wait()
    fmt.Printf("Done waiting\n")
}()

我不认为这应该有所作为,但是值得的是命令go test html.它超时的原因是因为我在运行它之前注入了导致无限循环的错误.为了增加混乱,我尝试使用go test net运行它.有一个超时,它正常工作.

I don't think it should make a difference, but for what it's worth the command is go test html. The reason it's timing out is because I'm injecting an error that causes an infinite loop before running it. To add to the confusion, I tried running it with go test net. There was a timeout, and it worked correctly.

推荐答案

问题似乎在于cmd.Process.Kill()不会杀死子进程.看到类似的问题子进程上的Process.Kill()

Looks like the problem is that cmd.Process.Kill() doesn't kill child processes. See this similar question Process.Kill() on child processes

我在此线程中找到了解决方案 https://groups.google .com/forum/#!topic/golang-nuts/XoQ3RhFBJl8

I found a solution in this thread https://groups.google.com/forum/#!topic/golang-nuts/XoQ3RhFBJl8

cmd := exec.Command( some_command )
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
cmd.Start()

pgid, err := syscall.Getpgid(cmd.Process.Pid)
if err == nil {
    syscall.Kill(-pgid, 15)  // note the minus sign
}

cmd.Wait()

请注意,这几乎肯定不能在所有平台上都有效-我目前在OSX Yosemite上,我敢打赌它也可以在大多数Linux上使用,但我还不够了解关于BSD有意见,我怀疑它是否可以在Windows上运行.

As a caveat this will almost certainly not work across platforms - I'm on OSX Yosemite at the moment, and I'd be willing to bet it'd work on most Linuxes as well, but I don't know enough about BSD to have an opinion and I doubt it would work on Windows.

这篇关于为什么不正确地终止子进程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆