diff --git a/libnetwork/internal/kvstore/boltdb/boltdb.go b/libnetwork/internal/kvstore/boltdb/boltdb.go index d79c6155c9..8b2c05140e 100644 --- a/libnetwork/internal/kvstore/boltdb/boltdb.go +++ b/libnetwork/internal/kvstore/boltdb/boltdb.go @@ -3,6 +3,8 @@ package boltdb import ( "bytes" "encoding/binary" + "errors" + "fmt" "os" "path/filepath" "sync" @@ -34,9 +36,20 @@ func New(path, bucket string) (store.Store, error) { } db, err := bolt.Open(path, filePerm, &bolt.Options{ - Timeout: time.Minute, + // The bbolt package opens the underlying db file and then issues an + // exclusive flock to ensures that it can safely write to the db. If + // it fails, it'll re-issue flocks every few ms until Timeout is + // reached. + // This nanosecond timeout bypasses that retry loop and make sure the + // bbolt package returns an ErrTimeout straight away. That way, the + // daemon, and unit tests, will fail fast and loudly instead of + // silently introducing delays. + Timeout: time.Nanosecond, }) if err != nil { + if errors.Is(err, bolt.ErrTimeout) { + return nil, fmt.Errorf("boltdb file %s is already open", path) + } return nil, err }