Go goroutines leaking

Issue

Following this post about go-routines leaking, https://www.ardanlabs.com/blog/2018/11/goroutine-leaks-the-forgotten-sender.html, i tried to solve my leaking code. But adding a buffer to the channel it did not do the trick.

My code

package main

import (
    "fmt"
    "runtime"
    "time"
)

func main() {
    fmt.Println(runtime.NumGoroutine())
    leaking()
    time.Sleep(5)
    fmt.Println(runtime.NumGoroutine())
}

func leaking() {
    errChang := make(chan int, 1)
    go func() {
        xx :=  return666()
        errChang <- xx
    }()
    fmt.Println("hola")
    return

    fmt.Println(<-errChang)
}

func return666() int {
    time.Sleep(time.Second * 1)
    return 6
}

My initial code did not use a buffer, leading to the go-routine in the leaking function, .. to leak. Following the post i expected that by adding a buffer to the channel, it would have avoided leaking.

Solution

Here, in the Go Playground, is your original code with a few slight modifications:

  • the delays are reduced, except for time.Sleep(5) which becomes time.Sleep(time.Second);
  • a return is removed because it becomes unnecessary;
  • a fmt.Println is commented out, because with both the return and the uncommented fmt.Println, go vet complains about the unreachable fmt.Println;
  • the channel stored in errChang is changed to unbuffered.

When run, its output is:

1
hola
2

(with a small delay before the 2), showing that indeed, the anonymous goroutine you started in function leaking is still running.

If we uncomment the commented-out fmt.Println, the output is:

1
hola
6
1

(with the same slight delay before the final 1) because we now wait for (and then print) the value computed in return666 and sent over channel errChang.

If we keep the commented-out fmt.Println commented out and make the channel buffered, the output becomes:

1
hola
1

as the anonymous goroutine is now able to push its value (6) into the channel.

The channel itself would be garbage collected, along with the single value stored inside it, as there are no remaining references to the channel at this point. Note, however, that simply making the channel buffered is not always sufficient. If we send two values down the channel, the program returns to printing:

1
hola
2

as the anonymous goroutine succeeds in putting 6 into the channel but then blocks trying to put 42 in as well.

Answered By – torek

Answer Checked By – Marie Seifert (GoLangFix Admin)

Leave a Reply

Your email address will not be published.