代码之家  ›  专栏  ›  技术社区  ›  leetom

如何为循环扫描的bufio扫描仪设置超时?

  •  0
  • leetom  · 技术社区  · 1 年前

    我正在使用golang来启动一个进程并监视输出。这个过程将运行很长一段时间,我需要能够发送一个信号来结束它。

    我有以下代码,它在大多数情况下都能很好地工作。但是,由于某些原因,进程可能没有输出,for循环将被阻止 Scan() 方法和无法从接收 processFinishChan .

    有没有一种简单的方法可以设置超时 扫描 方法我尝试了一个运行的解决方案 扫描 在另一个goroutine中,并使用另一个select从新的goroutine和一个超时通道接收,但考虑外部 for 循环,是否会有越来越多的goroutines被阻止 Scan ?

    // code that start the process...
    scanner := bufio.NewScanner(stdout)
    
    for {
        select {
        case <-processFinishChan: // send to this channel to terminate the process
            log.Println("Killing Process")
            err := cmdObject.Process.Kill()
            if err != nil {
                log.Printf("Error Killing: %v", err)
            } else {
                return
            }
        default:
            // default case, read the output of process and send to user.
            if !scanner.Scan() && scanner.Err() == nil {
                // reach EOF
                return
            }
            m := scanner.Bytes()
    
            WSOutChanHolder.mu.Lock()
            for _, ch := range WSOutChanHolder.data {
                ch <- m
            }
            WSOutChanHolder.mu.Unlock()
        }
    }
    
    0 回复  |  直到 1 年前
        1
  •  1
  •   Dylan Reimerink    1 年前

    假设 stdout 是的结果 cmdObject.StdoutPipe() ,在进程退出后等待时,读取器应关闭读取器并中断任何正在进行的读取。

    Wait将在看到命令退出后关闭管道,因此大多数调用方不需要自己关闭管道。

    所以,我们需要在一个单独的goroutine中终止这个过程,然后 Wait 杀死过程后,观察它的发生并关闭阅读器。

    // code that start the process...
    scanner := bufio.NewScanner(stdout)
    
    go func() {
        <-processFinishChan: // send to this channel to terminate the process
        log.Println("Killing Process")
        err := cmdObject.Process.Kill()
        if err != nil {
            log.Printf("Error Killing: %v", err)
        } 
    
        cmdObject.Wait()
    } ()
    
    for {
        // default case, read the output of process and send to user.
        if !scanner.Scan() && scanner.Err() == nil {
            // reach EOF
            return
        }
        m := scanner.Bytes()
    
        WSOutChanHolder.mu.Lock()
        for _, ch := range WSOutChanHolder.data {
            ch <- m
        }
        WSOutChanHolder.mu.Unlock()
    }