golang / tour

[mirror] A Tour of Go
BSD 3-Clause "New" or "Revised" License
1.53k stars 521 forks source link

memory leak in solution for Exercise: Equivalent Binary Trees? #739

Open Vogel-Guo opened 5 years ago

Vogel-Guo commented 5 years ago

solution with quit for Exercise: Equivalent Binary Trees Supposed we have two simple equivalent binary trees "1 3 5" and "2 3 5". When two goroutines "Walk" walks at leaf "1" and "2" concurrently,

if v1 != v2 {
    return false
}

this condition in function Same will be true and

close(quit)

will run.

func walkImpl(t *tree.Tree, ch, quit chan int) {
    if t == nil {
        return
    }
    walkImpl(t.Left, ch, quit)
    select {
    case ch <- t.Value:
        // Value successfully sent.
    case <-quit:
        return
    }
    walkImpl(t.Right, ch, quit)
}

Channel "quit" will receive message and the second case of select statement will execute. And then it will go back to the upper level function "walkImpl" and keep on running the last line walkImpl(t.Right, ch, quit). So is there goroutine leak under the circumstance, cause channel "quit" is already read out, which can't be read again in the upper level? Function "Walk" also can't go back to "close" handler.

0xDEAD commented 4 years ago

You can read from a closed channel as much as you like, it returns a infinite number of null-values of the channel-type (int 0 here). So, indeed walkImpl is still called for the "leftmost" branch of the current node in the tree (down to the leaf) but all of those calls will successfully read a value from quit and return.