mirror of
https://github.com/etcd-io/bbolt.git
synced 2025-05-31 11:42:30 +00:00
complete all cleanup operations in db.close() even if there is an error in the middle
Signed-off-by: caojiamingalan <alan.c.19971111@gmail.com>
This commit is contained in:
parent
287049ea83
commit
505fc0f7af
11
db.go
11
db.go
@ -649,9 +649,10 @@ func (db *DB) close() error {
|
|||||||
// Clear ops.
|
// Clear ops.
|
||||||
db.ops.writeAt = nil
|
db.ops.writeAt = nil
|
||||||
|
|
||||||
|
var errs []error
|
||||||
// Close the mmap.
|
// Close the mmap.
|
||||||
if err := db.munmap(); err != nil {
|
if err := db.munmap(); err != nil {
|
||||||
return err
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close file handles.
|
// Close file handles.
|
||||||
@ -660,18 +661,22 @@ func (db *DB) close() error {
|
|||||||
if !db.readOnly {
|
if !db.readOnly {
|
||||||
// Unlock the file.
|
// Unlock the file.
|
||||||
if err := funlock(db); err != nil {
|
if err := funlock(db); err != nil {
|
||||||
return fmt.Errorf("bolt.Close(): funlock error: %w", err)
|
errs = append(errs, fmt.Errorf("bolt.Close(): funlock error: %w", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the file descriptor.
|
// Close the file descriptor.
|
||||||
if err := db.file.Close(); err != nil {
|
if err := db.file.Close(); err != nil {
|
||||||
return fmt.Errorf("db file close: %s", err)
|
errs = append(errs, fmt.Errorf("db file close: %w", err))
|
||||||
}
|
}
|
||||||
db.file = nil
|
db.file = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
db.path = ""
|
db.path = ""
|
||||||
|
|
||||||
|
if len(errs) > 0 {
|
||||||
|
return errs[0]
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package failpoint
|
|||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
@ -23,3 +24,25 @@ func TestFailpoint_MapFail(t *testing.T) {
|
|||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.ErrorContains(t, err, "map somehow failed")
|
require.ErrorContains(t, err, "map somehow failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensures when munmap fails, the flock is unlocked
|
||||||
|
func TestFailpoint_UnmapFail_DbClose(t *testing.T) {
|
||||||
|
//unmap error on db close
|
||||||
|
//we need to open the db first, and then enable the error.
|
||||||
|
//otherwise the db cannot be opened.
|
||||||
|
f := filepath.Join(t.TempDir(), "db")
|
||||||
|
|
||||||
|
err := gofail.Enable("unmapError", `return("unmap somehow failed")`)
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, err = bolt.Open(f, 0666, nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.ErrorContains(t, err, "unmap somehow failed")
|
||||||
|
//disable the error, and try to reopen the db
|
||||||
|
err = gofail.Disable("unmapError")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
db, err := bolt.Open(f, 0666, &bolt.Options{Timeout: 30 * time.Second})
|
||||||
|
require.NoError(t, err)
|
||||||
|
err = db.Close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user