Back to all reviewers

Safe lock patterns

opentofu/opentofu
Based on 6 comments
Go

When implementing concurrent operations, ensure locks are acquired and released properly in all execution paths. Always use patterns that guarantee lock release, and document lock acquisition order to prevent deadlocks.

Concurrency Go

Reviewer Prompt

When implementing concurrent operations, ensure locks are acquired and released properly in all execution paths. Always use patterns that guarantee lock release, and document lock acquisition order to prevent deadlocks.

Key practices:

  1. Always release locks on all return paths - Use defer statements for cleanup to guarantee locks are released even on error paths:
func (d *Dir) InstallPackage(ctx context.Context, meta getproviders.PackageMeta) error {
    unlock, err := d.Lock(ctx, meta.Provider, meta.Version)
    if err != nil {
        return err
    }
    defer unlock() // Ensures lock is released on all return paths
    
    // Implementation...
}
  1. Document lock acquisition order - When acquiring multiple locks, establish and document a consistent order to prevent deadlocks:
// Acquire locks in consistent order: s3 first, then dynamoDB
s3LockId, err := c.s3Lock(info)
if err != nil {
    return "", err
}
dynamoLockId, err := c.dynamoDbLock(info)
if err != nil {
    return "", err
}
  1. Use explicit synchronization patterns - When coordinating multiple concurrent operations, use clear patterns with channels and wait groups:
lockResults := make(chan lockResult, len(platforms))
go func() {
    var wg sync.WaitGroup
    for _, platform := range platforms {
        wg.Add(1)
        go func(platform getproviders.Platform) {
            // Process work
            lockResults <- result
            wg.Done()
        }(platform)
    }
    wg.Wait()
    close(lockResults)
}()

for result := range lockResults {
    // Process results
}
  1. Handle concurrent error cases - When operating with multiple locks, handle partial failure cases explicitly by cleaning up already acquired resources.

Following these patterns helps prevent race conditions, deadlocks, and resource leaks in concurrent code.

6
Comments Analyzed
Go
Primary Language
Concurrency
Category

Source Discussions