如何向子进程发送信号?

3
我有些困难,无法在父进程和子进程之间发送信号。以下是子进程的代码,当它接收到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。

我该如何修改代码以使子进程接收到父进程发送的信号?


4
子进程不是你的程序,而是go命令。不要使用go run - JimB
@JimB 我在终端中尝试使用 go run child.go,并向其发送了一个信号,它正常工作。难道 exec.Command 有不同的工作方式吗? - poy
首先,exec.Command不是一个shell。但是它可以从shell中正常工作,那么你是如何测试它的? - JimB
1个回答

5
正如评论区中@JimB所提到的,问题出在go run上。 go run child.go会编译child并将其作为独立进程执行。如果你在go run child.go之后运行ps命令,你会看到两个进程正在运行。
你正在观察和发送信号的进程是go可执行文件,而不是child
用编译好的二进制文件exec.Command("child")替换exec.Command("go", "run", "child.go")就可以解决问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接