diff --git a/core/syncx/resourcemanager.go b/core/syncx/resourcemanager.go index cee3aba8a..a976cefde 100644 --- a/core/syncx/resourcemanager.go +++ b/core/syncx/resourcemanager.go @@ -23,6 +23,7 @@ func NewResourceManager() *ResourceManager { } // Close closes the manager. +// Don't use the ResourceManager after Close() called. func (manager *ResourceManager) Close() error { manager.lock.Lock() defer manager.lock.Unlock() @@ -33,8 +34,10 @@ func (manager *ResourceManager) Close() error { be.Add(err) } } - // reset resources - manager.resources = make(map[string]io.Closer) + + // release resources to avoid using it later + manager.resources = nil + return be.Err() } diff --git a/core/syncx/resourcemanager_test.go b/core/syncx/resourcemanager_test.go index d4456bfae..261bdb8ef 100644 --- a/core/syncx/resourcemanager_test.go +++ b/core/syncx/resourcemanager_test.go @@ -47,14 +47,28 @@ func TestResourceManager_GetResourceError(t *testing.T) { func TestResourceManager_Close(t *testing.T) { manager := NewResourceManager() - for i := 0; i < 10; i++ { _, err := manager.GetResource("key", func() (io.Closer, error) { return nil, errors.New("fail") }) assert.NotNil(t, err) } - err := manager.Close() - assert.NoError(t, err) - assert.Equal(t, 0, len(manager.resources)) + + if assert.NoError(t, manager.Close()) { + assert.Equal(t, 0, len(manager.resources)) + } +} + +func TestResourceManager_UseAfterClose(t *testing.T) { + manager := NewResourceManager() + _, err := manager.GetResource("key", func() (io.Closer, error) { + return nil, errors.New("fail") + }) + assert.NotNil(t, err) + if assert.NoError(t, manager.Close()) { + _, err = manager.GetResource("key", func() (io.Closer, error) { + return nil, errors.New("fail") + }) + assert.NotNil(t, err) + } } diff --git a/core/syncx/spinlock_test.go b/core/syncx/spinlock_test.go index 4fcc2bf91..e518d02d3 100644 --- a/core/syncx/spinlock_test.go +++ b/core/syncx/spinlock_test.go @@ -1,11 +1,14 @@ package syncx import ( + "runtime" "sync" + "sync/atomic" "testing" "time" "github.com/stretchr/testify/assert" + "github.com/tal-tech/go-zero/core/lang" ) func TestTryLock(t *testing.T) { @@ -37,3 +40,31 @@ func TestSpinLockRace(t *testing.T) { wait.Wait() assert.True(t, lock.TryLock()) } + +func TestSpinLock_TryLock(t *testing.T) { + var lock SpinLock + var count int32 + var wait sync.WaitGroup + wait.Add(2) + sig := make(chan lang.PlaceholderType) + + go func() { + lock.TryLock() + sig <- lang.Placeholder + atomic.AddInt32(&count, 1) + runtime.Gosched() + lock.Unlock() + wait.Done() + }() + + go func() { + <-sig + lock.Lock() + atomic.AddInt32(&count, 1) + lock.Unlock() + wait.Done() + }() + + wait.Wait() + assert.Equal(t, int32(2), atomic.LoadInt32(&count)) +}