【问题标题】:How do I send a signal to a child process?如何向子进程发送信号?
【发布时间】:2019-01-02 20:50:50
【问题描述】:

我在从父进程发送信号并在子进程中接收信号时遇到问题。

这是子进程的代码。它在收到 SIGINT 时退出。

// child.go
func main() {
    stop := make(chan os.Signal, 1)
    signal.Notify(stop, os.Interrupt)
    fmt.Println("started")

    <-stop
    fmt.Println("stopped")
}

这是父进程。它启动 child.go,发送 SIGINT,然后等待它退出。

// main.go
func main() {
    // Start child process
    cmd := exec.Command("go", "run", "child.go")
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    err := cmd.Start()
    if err != nil {
        _, _ = fmt.Fprintf(os.Stderr, "Start: " + err.Error())
        return
    }

    // Wait, then send signal
    time.Sleep(time.Millisecond * 500)
    err = cmd.Process.Signal(os.Interrupt)
    if err != nil {
        _, _ = fmt.Fprintf(os.Stderr, "Signal: " + err.Error())
        return
    }

    // Wait for child process to finish
    err = cmd.Wait()
    if err != nil {
        _, _ = fmt.Fprintf(os.Stderr, "Wait: " + err.Error())
    }
    return
}

这段代码应该打印started\nstopped以表明它按预期工作,但它只打印started并挂在cmd.Wait(),这意味着子进程没有收到信号。

当我运行go run child.go 时,它运行良好,所以我认为问题不在于该文件。我了解func (*Process) Signal 在 Windows 上不起作用;我正在使用 Linux。

如何修改代码,让子进程收到父进程发送的信号?

【问题讨论】:

  • 子进程不是你的程序,它是go 命令。不要使用go run
  • @JimB 我尝试从终端使用go run child.go,然后向它发送一个信号并且它工作。 exec.Command 的工作方式是否有所不同?
  • 一方面,exec.Command 不是外壳。但是,它在 shell 中的工作原理是一样的,那么你是如何测试它的呢?

标签: go signals


【解决方案1】:

正如@JimB 在 cmets 部分中提到的,go run 是您的问题。

go run child.go 将编译child 并将其作为自己的进程执行。如果您在go run child.go 之后运行ps,您将看到两个进程正在运行。

您正在观察和发送信号的进程是go 可执行文件,而不是child

exec.Command("go", "run", "child.go") 替换为编译后的二进制文件exec.Command("child"),它应该可以工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-30
    • 2022-06-15
    • 2020-03-25
    • 2019-12-28
    • 1970-01-01
    • 1970-01-01
    • 2019-04-11
    相关资源
    最近更新 更多