【问题标题】:Golang cant kill parent process from childGolang 不能从子进程中杀死父进程
【发布时间】:2014-09-18 20:23:50
【问题描述】:

最近几天我有点挣扎于分叉一个进程并从分叉的一个(孩子)杀死父母

我不知道为什么,但似乎根本没有杀死父母。首先,由于优雅的关闭过程,我在打开的连接保持进程运行的地方遇到了困难,但这不是那个问题。

如果我从终端向父级发送 SIGTERM,它工作得很好,但是当子级发送 SIGTERM 时它不会停止,强制退出不是正常关闭的选项原因。

edit * 进程仍在进程列表中。也许这是为了让父母跟踪它的孩子?

一些执行分叉的代码,也许我在这里做错了

func (s *Server) Upgrade() error {
    tl := s.listener.(*listener)

    addr := s.listener.Addr()
    name := fmt.Sprintf("%s:%s->", addr.Network(), addr.String())
    os.Setenv("PROX_NAME", name)

    fl, err := tl.File()
    if err != nil {
        return fmt.Errorf("Failed to extract file desciptor, %v", err)
    }

    fd := fl.Fd()

    argv0, err := exec.LookPath(os.Args[0])
    if err != nil {
        return fmt.Errorf("Failed to execute lookpath, %v", err)
    }

    noCloseOnExec(fd)

    files := make([]*os.File, fd+1)
    files[syscall.Stdin] = os.Stdin
    files[syscall.Stdout] = os.Stdout
    files[syscall.Stderr] = os.Stderr

    files[fd] = os.NewFile(fd, name)

    wd, err := os.Getwd()
    if err != nil {
        return err
    }

    os.Setenv("GPROXY_FD", fmt.Sprintf("%d", fd))
    os.Setenv("GPROXY_PID", fmt.Sprintf("%d", syscall.Getpid()))
    args := []string{"gproxy", "-debug", "start"}
    _, err = os.StartProcess(argv0, args, &os.ProcAttr{
        Dir:   wd,
        Env:   os.Environ(),
        Files: files,
    })

    return err
}

父级的终止

func termParentProcess() error {
    pid := syscall.Getppid()
    return syscall.Kill(pid, syscall.SIGTERM)
}

【问题讨论】:

  • termParentProcess 函数的上下文是什么?有没有任何定义的错误检查?
  • 嗯这是我的错我编辑它

标签: go signals


【解决方案1】:

长话短说,你不能分叉,这是一个非常古老且持续存在的问题here

您可以使用 https://github.com/icattlecoder/godaemon 之类的东西,但父母必须终止自己而不是孩子。

var isChild = flag.Bool("child", false, "parent pid")

func main() {
    flag.Parse()
    var s string
    if !*isChild { //parent
        fmt.Println("forking")
        files := make([]*os.File, 3)
        files[syscall.Stdin] = os.Stdin
        files[syscall.Stdout] = os.Stdout
        files[syscall.Stderr] = os.Stderr
        fmt.Println(os.StartProcess(os.Args[0], append(os.Args, "-child"), &os.ProcAttr{
            Dir:   "/tmp",
            Env:   os.Environ(),
            Files: files,
        }))
        fmt.Scan(&s) // block
    } else {
        ppid := os.Getppid()
        fmt.Println("ppid", ppid, "kill:", syscall.Kill(ppid, syscall.SIGTERM))
        time.Sleep(5 * time.Second)
        fmt.Println("child dying")
    }
}

【讨论】:

  • 我不认为他真的想“分叉”。他正在尝试执行一个新进程(恰好是 os.Args[0]),并让它在未来的某个时候杀死父进程。
  • @JimB 我误读了这个问题,反正 os.Getppid 很时髦。
【解决方案2】:

我的父进程不会在 TERM 信号上终止的问题是因为内部 for 循环不会中断。我修复了 for 循环并让 main 函数返回。如果在 Go 中 main 返回程序退出。很抱歉因为我自己的一个大错误而打扰你们

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    • 2017-04-15
    相关资源
    最近更新 更多