From f8eed9af12f0c51c8f67282f1487dc9f1ce1b2c4 Mon Sep 17 00:00:00 2001 From: 0xff-dev Date: Sun, 8 Oct 2023 15:45:20 +0800 Subject: [PATCH] fix: goroutine leak --- api/internal/utils/timedcall.go | 2 +- api/internal/utils/timedcall_test.go | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/api/internal/utils/timedcall.go b/api/internal/utils/timedcall.go index 0afadd0c3f..cda53f864b 100644 --- a/api/internal/utils/timedcall.go +++ b/api/internal/utils/timedcall.go @@ -10,7 +10,7 @@ import ( // TimedCall runs fn, failing if it doesn't complete in the given duration. // The description is used in the timeout error message. func TimedCall(description string, d time.Duration, fn func() error) error { - done := make(chan error) + done := make(chan error, 1) timer := time.NewTimer(d) defer timer.Stop() go func() { done <- fn() }() diff --git a/api/internal/utils/timedcall_test.go b/api/internal/utils/timedcall_test.go index 192edc48cd..6e01b29888 100644 --- a/api/internal/utils/timedcall_test.go +++ b/api/internal/utils/timedcall_test.go @@ -5,6 +5,7 @@ package utils_test import ( "fmt" + "runtime" "testing" "time" @@ -62,3 +63,15 @@ func TestTimedCallSlowWithError(t *testing.T) { t.Fail() } } + +func TestTimedCallGoroutineLeak(t *testing.T) { + beforeGroutine := runtime.NumGoroutine() + _ = TimedCall("expect no goroutine leaks", time.Duration(time.Second), func() error { + time.Sleep(2 * time.Second) + return fmt.Errorf("not done") + }) + afterGoroutine := runtime.NumGoroutine() + if beforeGroutine != afterGoroutine { + t.Fatal("goroutine leak") + } +}