V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Morriaty
V2EX  ›  程序员

有人遇到过 Golang select case 语句和 default 语句都没执行的情况吗?

  •  
  •   Morriaty · 2021-08-10 11:10:52 +08:00 · 2340 次点击
    这是一个创建于 1192 天前的主题,其中的信息可能已经有所发展或是发生改变。

    程序大致逻辑如下,会正常运行一段时间,receiving msgsleeping会交替打印,但运行一段时间后最后输出一段pipeline sleeping之后就再也没有日志了,没有pipeline terminate,没有 panic,也没有到 defer 那一步

    var sigChan = make(chan os.Signal, 1)
    
    func init() {
    	signal.Notify(
    		sigChan,
    		os.Kill,
    		os.Interrupt,
    		syscall.SIGHUP,
    		syscall.SIGINT,
    		syscall.SIGTERM,
    		syscall.SIGQUIT,
    	)
    }
    
    func (ip *InnerPipeline) Run() {
    
    	defer func() {
    		log.Infof("pipeline<%s> defer exit", ip.name)
    	}()
    
    	for {
    
    		select {
    		case im := <-ip.messageQueue:
    			log.Debugf("receiving msg %+v", im)
    
    			// some logic ....
                            xxxxxxxxxxxxxxx
    
    			log.Debugf("quit case")
    
    		case <-sigChan:
    			log.Infof("pipeline terminate")
    			return
    
    		default:
    			log.Debugf("current chan len: %d", len(ip.messageQueue))
    			
    			// some logic ....
                            xxxxxxxxxxxxxxx            
    
    			log.Debugf("pipeline<%s> sleeping...", ip.name)
    			time.Sleep(50 * time.Millisecond)
    		}
    	}
    }
    
    第 1 条附言  ·  2021-08-10 11:52:01 +08:00
    忘了描述了,主程序没有结束,msg produce 的地方依然在打印日志

    ```golang
    func main() {
    pipeline := NewInnerPipeline("name", 1000)

    // some msg produce logic
    xxxxxxxxx

    go pipeline.Run()

    // other logic
    xxxxxxx
    }

    ```
    13 条回复    2021-08-10 18:53:48 +08:00
    index90
        1
    index90  
       2021-08-10 11:41:59 +08:00
    大概率你的 main 函数还没等 Run 函数 return 就结束了
    paulter
        2
    paulter  
       2021-08-10 11:50:42 +08:00
    提问之前,起码先抽出一个最小可运行的 demo 程序,以便重现问题。
    Morriaty
        3
    Morriaty  
    OP
       2021-08-10 11:53:50 +08:00
    @index90 忘了描述了,主程序没有结束,msg produce 的地方依然在打印日志
    Hstar
        4
    Hstar  
       2021-08-10 11:55:44 +08:00
    建议排查 default 块里的代码, 精简到只有 log 和 Sleep 试试是否在循环
    gamexg
        5
    gamexg  
       2021-08-10 12:02:43 +08:00
    golang pprof 直接看卡在哪一步了
    fds
        6
    fds  
       2021-08-10 13:00:54 +08:00
    for 开始时打印下 ip.messageQueue
    nuk
        7
    nuk  
       2021-08-10 13:34:22 +08:00
    gdb 一把就知道了啊。。
    Morriaty
        8
    Morriaty  
    OP
       2021-08-10 14:25:22 +08:00
    @Hstar @fds 好的我试试
    @gamexg 我加下看看,但感觉不一定看得懂🤣
    @nuk 开发环境无法复现,生产环境要跑一两个小时才会出现这个问题,这种情况下怎么打断点啊?
    nuk
        9
    nuk  
       2021-08-10 16:27:57 +08:00
    @Morriaty 隔一会检查一下 log,要是太久没出现 log 就 dump stack 出来。。不过你这个问题我觉得像是 signal channel 过早关闭。。于是就在里面死循环了。。
    cyrivlclth
        10
    cyrivlclth  
       2021-08-10 17:31:05 +08:00
    可能是 some logic 里面的逻辑耗时太长卡住了吧。
    Morriaty
        11
    Morriaty  
    OP
       2021-08-10 17:32:42 +08:00
    @nuk 额,代码里是没有主动关闭 chan 的地方,而且就算关闭了,也会打出 pipeline terminate 日志吧
    Morriaty
        12
    Morriaty  
    OP
       2021-08-10 17:33:25 +08:00
    @cyrivlclth 如果是 some logic 堵住了,就不会打印 sleeping 的日志啊,实际日志是停在 sleeping 这里的
    nacosboy
        13
    nacosboy  
       2021-08-10 18:53:48 +08:00
    @Morriaty 我觉得也是 some logic 在特定场景下 block 住了,打印出的 sleeping 日志,可能是上一次循环打印出的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4302 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 10:14 · PVG 18:14 · LAX 02:14 · JFK 05:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.