Golang cant kill parent process from child

Last days i am kinda struggling with forking a process and kill the parent from the forked one(child)

I don't know why but it seems not to kill the parent at all. first i tough it where the open connections that keeps the process running because of the graceful shutdown process, But its not that issue.

if i send SIGTERM to the parent from the terminal it worked perfect, but when the child send SIGTERM it does not stop, force quitting is no option cause of graceful shutdown.

edit * the processes are still in the process list. Maybe that is for parent to track its children?

Some code that does the fork, maybe i do something wrong here

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
}

the termination of the parent

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

Upvotes: 0

Views: 2042

Answers (2)

The problem my parent process wont terminate on a TERM signal is because of a inner for loop that wont break. I fixed the for loop and let the main function return. If in Go the main returns the program exits. sorry for bothering you guys with a big mistake of myself

Upvotes: 1

OneOfOne
OneOfOne

Reputation: 99195

Long story short, you can't fork, there's a very old and ongoing issue for it here.

You could use something like https://github.com/icattlecoder/godaemon but the parent will have to terminate itself not the child.

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")
    }
}

Upvotes: 2

Related Questions