diff --git a/CHANGELOG.md b/CHANGELOG.md index 87bda6d85..c15495599 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ - [REMOVED] `FromData` is considered unused so was removed. - [FEATURE] Added option WALSegmentSize -1 to disable the WAL. - [BUGFIX] Fsync the meta file to persist it on disk to avoid data loss in case of a host crash. - - [BUGFIX] Fix fd and vm_area leak on error path in chunks.NewDirReader + - [BUGFIX] Fix fd and vm_area leak on error path in chunks.NewDirReader. + - [BUGFIX] Fix fd and vm_area leak on error path in index.NewFileReader. ## 0.6.1 - [BUGFIX] Update `last` after appending a non-overlapping chunk in `chunks.MergeOverlappingChunks`. [#539](https://github.com/prometheus/tsdb/pull/539) diff --git a/index/index.go b/index/index.go index 3f79bd7a7..9e5ceccec 100644 --- a/index/index.go +++ b/index/index.go @@ -29,6 +29,7 @@ import ( "github.com/pkg/errors" "github.com/prometheus/tsdb/chunks" "github.com/prometheus/tsdb/encoding" + tsdb_errors "github.com/prometheus/tsdb/errors" "github.com/prometheus/tsdb/fileutil" "github.com/prometheus/tsdb/labels" ) @@ -625,7 +626,15 @@ func NewFileReader(path string) (*Reader, error) { if err != nil { return nil, err } - return newReader(realByteSlice(f.Bytes()), f) + r, err := newReader(realByteSlice(f.Bytes()), f) + if err != nil { + var merr tsdb_errors.MultiError + merr.Add(err) + merr.Add(f.Close()) + return nil, merr + } + + return r, nil } func newReader(b ByteSlice, c io.Closer) (*Reader, error) { diff --git a/index/index_test.go b/index/index_test.go index 70aa09756..b82d07d2a 100644 --- a/index/index_test.go +++ b/index/index_test.go @@ -412,3 +412,18 @@ func TestReaderWithInvalidBuffer(t *testing.T) { _, err := NewReader(b) testutil.NotOk(t, err) } + +// TestNewFileReaderErrorNoOpenFiles ensures that in case of an error no file remains open. +func TestNewFileReaderErrorNoOpenFiles(t *testing.T) { + dir := testutil.NewTemporaryDirectory("block", t) + + idxName := filepath.Join(dir.Path(), "index") + err := ioutil.WriteFile(idxName, []byte("corrupted contents"), 0644) + testutil.Ok(t, err) + + _, err = NewFileReader(idxName) + testutil.NotOk(t, err) + + // dir.Close will fail on Win if idxName fd is not closed on error path. + dir.Close() +}