goroutine leak at cache.go:1079 - `runJanitor`
package main
import (
"testing"
"time"
"github.com/patrickmn/go-cache"
"go.uber.org/goleak"
)
func leaktest(t *testing.T) {
defer goleak.VerifyNone(t)
cache.New(5*time.Minute, 10*time.Minute)
}
func main() {
testSuite := []testing.InternalTest{{Name: "leaktest", F: leaktest}}
testing.Main(func(a, b string) (bool, error) { return a == b, nil }, testSuite, nil, nil)
}
Run above code (https://go.dev/play/p/PxN4Q4-F2rG)
Result:
[Goroutine 6 in state select, with github.com/patrickmn/go-cache.(*janitor).Run on top of the stack:
goroutine 6 [select]:
github.com/patrickmn/go-cache.(*janitor).Run(0xc0002f16d0, 0x0?)
/home/wxh/go/pkg/mod/github.com/patrickmn/[email protected]+incompatible/cache.go:1079 +0x85
created by github.com/patrickmn/go-cache.runJanitor
/home/wxh/go/pkg/mod/github.com/patrickmn/[email protected]+incompatible/cache.go:1099 +0xed
]
It looks like https://github.com/patrickmn/go-cache/blob/v2.1.0/cache.go#L1076-L1087 does not handle exit condition properly.
it's work
import (
"runtime"
"testing"
"time"
"github.com/patrickmn/go-cache"
"go.uber.org/goleak"
)
func leaktest(t *testing.T) {
defer goleak.VerifyNone(t)
cache.New(5*time.Minute, 10*time.Minute)
runtime.GC()
}
func main() {
testSuite := []testing.InternalTest{{Name: "leaktest", F: leaktest}}
testing.Main(func(a, b string) (bool, error) { return a == b, nil }, testSuite, nil, nil)
}
I am also getting the similar kind of error as follows
range_service | goroutine 876 [select, 2 minutes]:
range_service | github.com/patrickmn/go-cache.(*janitor).Run(0xc001627fb0, 0xc0011b9140?)
range_service | /Users/jay/go/pkg/mod/github.com/patrickmn/[email protected]+incompatible/cache.go:1079 +0x85
range_service | created by github.com/patrickmn/go-cache.runJanitor
range_service | /Users/jay/go/pkg/mod/github.com/patrickmn/[email protected]+incompatible/cache.go:1099 +0xed
range_service |
range_service | goroutine 877 [select, 5 minutes]:
range_service | github.com/patrickmn/go-cache.(*janitor).Run(0xc001634050, 0x0?)
range_service | /Users/jay/go/pkg/mod/github.com/patrickmn/[email protected]+incompatible/cache.go:1079 +0x85
range_service | created by github.com/patrickmn/go-cache.runJanitor
range_service | /Users/jay/go/pkg/mod/github.com/patrickmn/[email protected]+incompatible/cache.go:1099 +0xed
@vithnilica Can you explain how runtime.GC() is helping and when to call this function. I am really new to go and don't understand much about memory leaks and all so can you please give an example to explain it better.
Thanks
It is not memory leaks (or goroutine leak). "go.uber.org/goleak" test does not wait for "garbage collector".
It is not memory leaks (or goroutine leak). "go.uber.org/goleak" test does not wait for "garbage collector".
Can you please explain why I am getting the error(cause of the error) and how will adding a routine.GC() after every cache creation helps to resolve the error.
The test counts the number of goroutines at the beginning and at the end. You need to clean up the memory (garbage collection) before terminating the test. Golang typically does this with a delay. Before releasing an object from memory, the Golang calls a finalizer that terminates the goroutine. Finalizer registration in code: https://github.com/patrickmn/go-cache/blob/master/cache.go#L1123 About finalizer: https://medium.com/a-journey-with-go/go-finalizers-786df8e17687 About garbage collection: https://tip.golang.org/doc/gc-guide