2016-02-16 13:19
浏览 166


Given is the following code:

package main
import (


func createPeasants() map[string]*exec.Cmd {
    peasants := map[string]*exec.Cmd{}
    for i := 0; i < NUMBER_OF_PEASANTS; i++ {
        name := fmt.Sprintf("peasant#%d", i + 1)
        fmt.Printf("[master] Start %s...
", name)
        cmd := exec.Command(os.Args[0], name)
        cmd.Stderr = os.Stderr
        cmd.Stdin = os.Stdin
        cmd.Stdout = os.Stdout
        if err := cmd.Start(); err != nil {
        peasants[name] = cmd
    return peasants

func masterWaitForSignal(c chan os.Signal) {
    for true {
        s := <-c
        fmt.Printf("[master] Got signal %v but still running...
", s)

func peasantWaitForSignal(name string, c chan os.Signal) {
    s := <-c
    fmt.Printf("[%s] Got signal %v and will exit not with code 66
", name, s)

func waitForPeasants(peasants map[string]*exec.Cmd) {
    for name, peasant := range peasants {
        if err := peasant.Wait(); err != nil {
            if exitError, ok := err.(*exec.ExitError); ok {
                waitStatus := exitError.Sys().(syscall.WaitStatus)
                fmt.Printf("[master] %s ended with exit code %d.
", name, waitStatus.ExitStatus())
            } else {

func actAsMaster() {
    c := make(chan os.Signal, 1)
    signal.Notify(c, os.Interrupt)

    peasants := createPeasants()

    fmt.Printf("[master] Started.
    go masterWaitForSignal(c)
    fmt.Printf("[master] Done.

func actAsPeasant(name string) {
    c := make(chan os.Signal, 1)
    signal.Notify(c, os.Interrupt)

    fmt.Printf("[%s] Started.
", name)
    peasantWaitForSignal(name, c)
    fmt.Printf("[%s] Done.
", name)

func main() {
    if len(os.Args) > 1 {
    } else {

When I run the code and hit [Ctrl]+[C] (while it runs) the following output it produced:

$ go run signaldemo.go 
[master] Start peasant#1...
[master] Start peasant#2...
[master] Start peasant#3...
[peasant#1] Started.
[master] Started.
[peasant#2] Started.
[peasant#3] Started.
^C[peasant#2] Got signal interrupt and will exit not with code 66
[peasant#1] Got signal interrupt and will exit not with code 66
[master] Got signal interrupt but still running...
[master] peasant#1 ended with exit code 66.
[master] peasant#2 ended with exit code 66.
[peasant#3] Got signal interrupt and will exit not with code 66
[master] peasant#3 ended with exit code 66.
[master] Done.

How can I prevent that the children receives the Interrupt signal? But I do not want to rewrite the children. A change in the calling process is required.

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dtvgo28624 2016-02-16 14:23

    The child processes are starting in the same process group by default, and your shell is sending the signal to all the processes at once when you press ctrl+c. This is the default behavior of the shell to try and clean up when you interrupt a program.

    The child processes won't receive signals sent directly to the parent.

    If you want to prevent the ctrl+c behavior, you can force the child processes to start in their own process groups with with the Setpgid and Pgid fields in syscall.SysProcAttr before starting the processes.

    cmd.SysProcAttr = &syscall.SysProcAttr{
        Setpgid: true,
        Pgid:    0,
    打赏 评论

相关推荐 更多相似问题