GOLANG:致命错误:所有goroutines都睡着了 - 僵局

时间:2015-02-03 13:51:36

标签: go deadlock goroutine

package main
import (
    "fmt"
    "os"
    "os/exec"
    "bufio"
    "reflect"
)

func runTheCommand(ch chan<- string, cmD string)  {
    ouT,_ := exec.Command("sh","-c",cmD).Output()
    ch <- string(ouT)
}
// Readln returns a single line (without the ending \n) from the input buffered reader. An error is returned iff there is an error with the buffered reader.
func Readln(r *bufio.Reader) (string, error) {
    var (isPrefix bool = true
        err error = nil 
        line, ln []byte
    )   
    for isPrefix && err == nil {
        line, isPrefix, err = r.ReadLine()
        ln = append(ln, line...)
    }   
    return string(ln),err
}



func main() {
    var chans = []chan string{}
    f, _ := os.Open("../tmpStatus.config")
    r := bufio.NewReader(f)
    cmD, e := Readln(r)
    for e == nil {
        ch := make(chan string)
        chans = append(chans, ch) 
        go runTheCommand(ch,cmD)
        cmD,e = Readln(r)
    }   

    cases := make([]reflect.SelectCase, len(chans))
    for i, ch := range chans {
        cases[i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ch)}
    }   

    remaining := len(cases)
    for remaining > 0 { 
        chosen, value, ok := reflect.Select(cases)
        if !ok {
            cases[chosen].Chan = reflect.ValueOf(nil)
            remaining -= 1
            continue
        }
        fmt.Printf("%s", value.String())
    }   
}    

此代码正确打印出通道中的所有接收值。 但最终它出现了以下错误:

  

致命错误:所有goroutine都睡着了 - 死锁!

     

goroutine 1 [select]:reflect.rselect(0xc200283480,0x22,0x22,   0xffffffffffffffff,0x0,...)           /usr/local/go/src/pkg/runtime/chan.c:1212 + 0x10d    reflect.Select(0xc200066800,0x22,0x22,0x1,0x0,...)           /usr/local/go/src/pkg/reflect/value.go:1957 + 0x1fb

我是GO的新人。我提到谷歌并以某种方式设法写了一个工作代码。我完全不了解这个脚本是如何工作的,尤其是反射包命令。我的目的是并行执行../tmpStatus.config文件中列出的unix命令并打印出结果。我很高兴GO提供的并发功能,因此决定尝试一下。现在它正在快速打印结果。直到现在,我一个接一个地在python中这样做。 我在go版本go1.1.2 linux / amd64中安装了这个脚本到自定义位置。 知道为什么会发生僵局吗?

1 个答案:

答案 0 :(得分:2)

看起来你正试图从一个文件中读取,然后将工作分成多个工作人员(扇出)。我没有看到代码中的任何通道关闭。有关我所指的模式的示例,请参阅https://gist.github.com/kylewolfe/7c54018a9ed16517c0dd。对于文件的每一行,您将读入一个通道,x工作人员将从中读取(并反映/工作)。