怎么保证进程结束时,能关闭掉子进程(多次监听信号量的问题)

2022-08-19 17:20:18 +08:00
 dzdh

场景:

程序依赖另外一个程序,并开放个端口。遂启动时先 process:=exec.Command() process.Start().

问题来了,每次 ctrl+c 退出时,这个子进程就孤儿了。

所以想:

监听个 SIGINT 信号,信号来时直接 p.Kill()。测试,好使。

然后就封装了一下。

#伪代码
#proj/intenal/process/process.go
func(p *process) Go() {
    p.cmd.Start()
    chan ...signal
    os.Notify....
    go func  <-chan; p.cmd.Kill()
}

新问题:ctrl+c 后。子进程退出了,主进程还活着。

不想 在项目里显式的 exec.Command(....一堆。

既然连 exec.Command 都没有了。也就不想在最外层监听信号再传到自己封的 process 里。

那么问题来了:怎么能在内部包的里面使用信号还不影响信号本身对程序的影响呢?

其实就是想:

#main
func main() {
    internal.process.New().Go() # 一行,没有信号,没有需要关注的 ctx
    http.ServerStart()
    https.ServerStart()
    rpc.ServerStart()

    # 整个 main 就几行就行了。
}
1584 次点击
所在节点    Go 编程语言
9 条回复
ch2
2022-08-19 17:47:07 +08:00
server 为什么要 ctrl+c 终止?
codehz
2022-08-19 17:58:00 +08:00
可以试试
flag := unix.SIGHUP
if err := unix.Prctl(unix.PR_SET_PDEATHSIG, uintptr(flag), 0, 0, 0); err != nil {
return
}
reter
2022-08-19 17:59:01 +08:00
看了文档,当你监听了 SIGINT 信号,就相当于覆盖了 go 对 SIGINT 的默认行为(退出程序)

简单方法:让 main 函数也监听 SIGINT 信号。
dzdh
2022-08-19 18:09:17 +08:00
go1.19 的 SysProcAttr 新增一个 Pdeathsig

在 start 前 cmd.Process.SysProcAttr=&syscall.SysProcAttr{ Pdeathsig: syscall.SIGTERM} 即可。

不知道有啥坑。https://go.dev/issue/27505.
dzdh
2022-08-19 18:09:31 +08:00
@ch2 本地开发贼鸡儿麻烦。
Nitroethane
2022-08-19 18:33:02 +08:00
用 `exec.CommandContext()` 方法,你 ctrl-c 的时候 cancel parent context ,起的这个子进程会被自动 kill 掉。
glasslion
2022-08-19 20:16:16 +08:00
豆瓣曾经开源过一个名字很没品的项目:曹娥

https://github.com/douban/CaoE
monkeyNik
2022-08-19 20:27:23 +08:00
为啥不使用 socketpair ?进程退出,另一端套接字直接 read 返回 0
a632079
2022-08-20 22:37:24 +08:00
按你的需求,如果我没理解错的话,直接在监听 SIGINT 的自定义方法末尾补个 os.Exit 就好了吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/874044

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX