最后几天我有点挣扎着分叉一个过程并从分叉的孩子身上杀死父母(孩子)
我不知道为什么但似乎根本不会杀死父母。首先,我强调它是由于优雅的关闭过程而保持流程运行的开放连接,但不是那个问题。
如果我从终端向父节点发送SIGTERM它完美无缺,但是当孩子发送SIGTERM时它不会停止,强制退出是没有选择导致正常关闭的原因。
编辑*流程仍在流程列表中。也许这是父母跟踪其孩子的?
执行fork的一些代码,也许我在这里做错了
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)
}
答案 0 :(得分:2)
长话短说,你不能分叉,这是一个非常古老而持续的问题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")
}
}
答案 1 :(得分:1)
我的父进程不会在TERM信号上终止的问题是因为内部for循环不会中断。我修复了for循环并让main函数返回。如果在Go中,main返回程序退出。很抱歉打扰你们,我自己犯了一个大错误