Why isn't my function returning?

Issue

Below is a function that starts an external process, matches a regular expression against the process’ standard output, and returns the contents of the match.

func (c *Colony) startCircuit(peer *string) (string, error) {
    var (
        err        error
        cmd        *exec.Cmd
        anchorChan chan string
    )

    // ... (omitted for readability)

    // get the anchor from standard output
    go func() {
        defer out.Close()

        anchorChan = make(chan string)
        for scanner := bufio.NewScanner(out); scanner.Scan(); {
            line := scanner.Text()
            if anchor := reRootAnchor.FindString(line); anchor != "" {
                log.Println("Started circuit server with anchor:", anchor)
                anchorChan <- anchor
                break
            }
        }
    }()

    anchor := <-anchorChan
    return anchor, err
}

When running the function, I obtain the following output, which shows that a match is indeed found and (presumably) pushed into anchorChan:

2016/05/22 14:04:36 Started circuit server with anchor: circuit://[::]:36195/20666/Q431cc5fe613aa04b

However, startCircuit‘s caller seems to hang. Here is the relevant bit of code:

rootAnchor, err := c.startCircuit(peer)
if err != nil {
    return "", err
}
log.Fatal(rootAnchor) // DEBUG

Why is startCircuit hanging indefinitely instead of returning?

Solution

The problem is in fact quite simple. Hint: the following code ends in a deadlock.

package main

import "fmt"

func main() {
    var c chan string

    go func() {
        c = make(chan string)
        c <- "42"
    }()

    str := <-c
    fmt.Println(str)
}

From there, the problem is trivial. Your channel is not initialized when you start the goroutine. There is a race with the two goroutines, and apparently go cannot decide which should have the priority.

So, your answer is: call make(chan ...) before the goroutine starts, it should solve your problem. There is a perfect example of this in effective go.

Answered By – T. Claverie

Answer Checked By – Marilyn (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.