From c540f30f82c745f14864084e4043f3b55c60c757 Mon Sep 17 00:00:00 2001 From: Ulderico Cirello Date: Thu, 23 Mar 2023 09:23:45 -0700 Subject: [PATCH] dynamolock/v2: fix lock race condition Addresses #184 --- v2/client_test.go | 7 ++++--- v2/lock.go | 7 ++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/v2/client_test.go b/v2/client_test.go index b8d8c44..4d068c5 100644 --- a/v2/client_test.go +++ b/v2/client_test.go @@ -26,7 +26,6 @@ import ( "net" "os" "os/exec" - "path/filepath" "strings" "sync" "testing" @@ -45,10 +44,11 @@ func TestMain(m *testing.M) { if err != nil { panic("cannot execute tests without Java") } - _ = os.Remove(filepath.Join("local-dynamodb", "shared-local-instance.db")) // unconditionally remove state file ctx, cancel := context.WithCancel(context.Background()) - cmd := exec.CommandContext(ctx, javaPath, "-Djava.library.path=./DynamoDBLocal_lib", "-jar", "DynamoDBLocal.jar", "-sharedDb") + cmd := exec.CommandContext(ctx, javaPath, "-Djava.library.path=./DynamoDBLocal_lib", "-jar", "DynamoDBLocal.jar", "-sharedDb", "-inMemory") cmd.Dir = "local-dynamodb" + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdout if err := cmd.Start(); err != nil { panic("cannot start local dynamodb:" + err.Error()) } @@ -61,6 +61,7 @@ func TestMain(m *testing.M) { c.Close() break } + time.Sleep(1 * time.Second) exitCode := m.Run() cancel() cmd.Wait() diff --git a/v2/lock.go b/v2/lock.go index 3ac10d3..08eacf7 100644 --- a/v2/lock.go +++ b/v2/lock.go @@ -121,6 +121,11 @@ func (l *Lock) AdditionalAttributes() map[string]types.AttributeValue { // "danger zone". It returns false if the lock has not been released and the // lock has not yet entered the "danger zone" func (l *Lock) IsAlmostExpired() (bool, error) { + if l == nil { + return false, ErrLockAlreadyReleased + } + l.semaphore.Lock() + defer l.semaphore.Unlock() t, err := l.timeUntilDangerZoneEntered() if err != nil { return false, err @@ -143,7 +148,7 @@ func (l *Lock) timeUntilDangerZoneEntered() (time.Duration, error) { if l.sessionMonitor == nil { return 0, ErrSessionMonitorNotSet } - if l.IsExpired() { + if l.isExpired() { return 0, ErrLockAlreadyReleased } return l.sessionMonitor.timeUntilLeaseEntersDangerZone(l.lookupTime), nil