V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
dzdh
V2EX  ›  Go 编程语言

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

  •  
  •   dzdh · 2022-08-19 17:20:18 +08:00 · 1553 次点击
    这是一个创建于 816 天前的主题,其中的信息可能已经有所发展或是发生改变。

    场景:

    程序依赖另外一个程序,并开放个端口。遂启动时先 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 就几行就行了。
    }
    
    9 条回复    2022-08-20 22:37:24 +08:00
    ch2
        1
    ch2  
       2022-08-19 17:47:07 +08:00   ❤️ 1
    server 为什么要 ctrl+c 终止?
    codehz
        2
    codehz  
       2022-08-19 17:58:00 +08:00 via iPhone
    可以试试
    flag := unix.SIGHUP
    if err := unix.Prctl(unix.PR_SET_PDEATHSIG, uintptr(flag), 0, 0, 0); err != nil {
    return
    }
    reter
        3
    reter  
       2022-08-19 17:59:01 +08:00
    看了文档,当你监听了 SIGINT 信号,就相当于覆盖了 go 对 SIGINT 的默认行为(退出程序)

    简单方法:让 main 函数也监听 SIGINT 信号。
    dzdh
        4
    dzdh  
    OP
       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
        5
    dzdh  
    OP
       2022-08-19 18:09:31 +08:00
    @ch2 本地开发贼鸡儿麻烦。
    Nitroethane
        6
    Nitroethane  
       2022-08-19 18:33:02 +08:00
    用 `exec.CommandContext()` 方法,你 ctrl-c 的时候 cancel parent context ,起的这个子进程会被自动 kill 掉。
    glasslion
        7
    glasslion  
       2022-08-19 20:16:16 +08:00
    豆瓣曾经开源过一个名字很没品的项目:曹娥

    https://github.com/douban/CaoE
    monkeyNik
        8
    monkeyNik  
       2022-08-19 20:27:23 +08:00 via iPhone
    为啥不使用 socketpair ?进程退出,另一端套接字直接 read 返回 0
    a632079
        9
    a632079  
       2022-08-20 22:37:24 +08:00
    按你的需求,如果我没理解错的话,直接在监听 SIGINT 的自定义方法末尾补个 os.Exit 就好了吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1051 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 20:10 · PVG 04:10 · LAX 12:10 · JFK 15:10
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.