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

求助一个 Go 关闭 Pending 的 goroutine

  •  
  •   xxxxware · 2022-03-22 14:50:45 +08:00 · 1927 次点击
    这是一个创建于 972 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在将 filebeat 源码嵌入项目

    	go func(){
                if err := cmd.Filebeat(inputs.Init, cmd.FilebeatSettings()).Execute(); err != nil {
                    os.Exit(1)
                }
            }
    

    这个 cmd.Filebeat().Execute() 可以理解为 time.sleep(无限大)会一直 pending, 我怎么样才能关掉这个 goroutine 呢? time.sleep(无限大)的情况也没有办法去 select context

    谢谢大家!

    20 条回复    2022-03-23 17:58:05 +08:00
    lev2048
        1
    lev2048  
       2022-03-22 15:40:34 +08:00
    go 没发通过其他 goroutine kill 掉 goroutine, 加个 cmd 脚本调用,改成非阻塞吧
    jim9606
        2
    jim9606  
       2022-03-22 16:17:44 +08:00
    按照 go 的 api 设计风格,阻塞调用是通过 deadline 防止无限阻塞的。通过 SetDeadline 设置后(注意是记录绝对时间,需要反复设置)阻塞调用即使未成功也要在 deadline 返回,好让 goroutine 有机会检查是否需要终止流程。
    你找找你用的库有没有这种 api 吧?
    freshgoose
        3
    freshgoose  
       2022-03-22 16:21:28 +08:00
    不管是 go 的 goroutine 还是 python 的 Thread ,你都不可能有办法从代码本身关闭或杀死,只能在程序里自己 return ,你 return 了它才会释放。
    xmge
        4
    xmge  
       2022-03-22 16:22:54 +08:00
    做不到,因为某个 goroutine 无法关闭其他 goroutine 。
    useben
        5
    useben  
       2022-03-22 17:49:39 +08:00
    我看不懂评论区了...
    tairan2006
        6
    tairan2006  
       2022-03-22 18:00:26 +08:00
    做不到,这种情况建议你用多进程……如果你改不了 Filebeat 的代码的话
    xxxxware
        7
    xxxxware  
    OP
       2022-03-22 18:00:28 +08:00
    @lev2048 @jim9606 @freshgoose @xmge 谢谢各位, 是的语言层面就没有 goroutine id 这种东西,最开始设计就设计成不能关闭。 现在碰到到情况是我的源码需要调用一个 go 写的软件,并二次开发其中的代码(需要在主程序中调用源码中的函数),这个软件是 cmd 形式的(所以代码内部没有关闭的函数)。
    感觉没路子走了 手动笑哭
    xxxxware
        8
    xxxxware  
    OP
       2022-03-22 18:01:21 +08:00
    cmd 脚本调用的话,就没办法通信, 和一次性交叉编译了
    xxxxware
        9
    xxxxware  
    OP
       2022-03-22 18:02:23 +08:00
    @jim9606 是的, 想避开多进程就是想通信和交叉编译更方便
    mengyx
        10
    mengyx  
       2022-03-22 20:25:39 +08:00
    你可以将 Execute 修改为 ExecuteContext ,通过 Context 的 CancelFunc 来从外部终止此 goroutine
    labulaka521
        11
    labulaka521  
       2022-03-22 20:50:24 +08:00 via iPhone
    改下内部实现加个 ctx ?
    kwanzaa
        12
    kwanzaa  
       2022-03-22 21:16:11 +08:00
    被调用方写的有问题,没有 ctx 或其他方式停止任务。
    buffzty
        13
    buffzty  
       2022-03-22 21:33:25 +08:00
    加个信号 收工
    xxxxware
        14
    xxxxware  
    OP
       2022-03-23 09:20:48 +08:00
    @mengyx 和我的想法完全一致, 我调了 cancel 但是他还在运行, 哭了
    xxxxware
        15
    xxxxware  
    OP
       2022-03-23 09:22:18 +08:00
    @labulaka521 这个 cmd 库有 ctx , 我调了没有反应。 不知道是不是使用问题
    xxxxware
        16
    xxxxware  
    OP
       2022-03-23 09:27:25 +08:00
    ```
    c := cmd.Filebeat(inputs.Init, cmd.FilebeatSettings())
    ctx, cancel := context.WithCancel(context.Background)
    go func(){
    if err := c.ExecuteContextFunction(ctx); err != nil {
    os.Exit(1)
    }
    }
    time.sleep( 10 * time.Second )
    cancel()
    time.sleep( 10000 * time.Second )
    ```
    cmd.Filebeat() 的返回类型中有 ctx , 我改了一下源码由在里面新建变为传入一个 ctx , 调用 cancel 后控制台还是在输出 filebeat 的日志
    lev2048
        17
    lev2048  
       2022-03-23 13:46:32 +08:00
    你试试分两个程序?把阻塞这个操作包到一个 go 程序里,然后在主程序通过 cmd 包 执行,获取 pid ,停止 kill pid ?
    lev2048
        18
    lev2048  
       2022-03-23 13:47:07 +08:00
    @lev2048 来把阻塞操作变成非阻塞
    mengyx
        19
    mengyx  
       2022-03-23 13:51:46 +08:00
    仔细看了一下 filebeat ,里面会使用到 os.Exit 。 那还是建议拆成两个进程比较好
    xxxxware
        20
    xxxxware  
    OP
       2022-03-23 17:58:05 +08:00
    @mengyx @lev2048 谢谢 确实没有注意到 里面有调用 os.Exit 。已经通过 exec.commandContext 拆成两个进程,拿 cancel 去关闭了。 只能做进程通信啦
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5894 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 02:42 · PVG 10:42 · LAX 18:42 · JFK 21:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.