fix: panic when checkpoint directory is empty (#9687)

Calling `wal.NewSegmentBufReader()` without any segments would cause a
`panic` resulting in prometheus crashing. This patch fixes the panic by
making segmentBufReader return a EOF if there are not segments.

This also means an empty checkpoint directory which should never be the
case unless it has been tampered with (or has issues due to the
underlying filesystem e.g. NFS) would be ignored by Prometheus and would
continue to run instead of the current behaviour which is to panic.

Fixes: https://github.com/prometheus/prometheus/issues/9605

Signed-off-by: Sunil Thaha <sthaha@redhat.com>
This commit is contained in:
Sunil Thaha 2021-11-17 21:09:04 +10:00 committed by GitHub
parent 042007f9ee
commit a484a83d4a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -878,6 +878,10 @@ type segmentBufReader struct {
// nolint:revive // TODO: Consider exporting segmentBufReader // nolint:revive // TODO: Consider exporting segmentBufReader
func NewSegmentBufReader(segs ...*Segment) *segmentBufReader { func NewSegmentBufReader(segs ...*Segment) *segmentBufReader {
if len(segs) == 0 {
return &segmentBufReader{}
}
return &segmentBufReader{ return &segmentBufReader{
buf: bufio.NewReaderSize(segs[0], 16*pageSize), buf: bufio.NewReaderSize(segs[0], 16*pageSize),
segs: segs, segs: segs,
@ -886,9 +890,10 @@ func NewSegmentBufReader(segs ...*Segment) *segmentBufReader {
// nolint:revive // nolint:revive
func NewSegmentBufReaderWithOffset(offset int, segs ...*Segment) (sbr *segmentBufReader, err error) { func NewSegmentBufReaderWithOffset(offset int, segs ...*Segment) (sbr *segmentBufReader, err error) {
if offset == 0 { if offset == 0 || len(segs) == 0 {
return NewSegmentBufReader(segs...), nil return NewSegmentBufReader(segs...), nil
} }
sbr = &segmentBufReader{ sbr = &segmentBufReader{
buf: bufio.NewReaderSize(segs[0], 16*pageSize), buf: bufio.NewReaderSize(segs[0], 16*pageSize),
segs: segs, segs: segs,
@ -910,6 +915,10 @@ func (r *segmentBufReader) Close() (err error) {
// Read implements io.Reader. // Read implements io.Reader.
func (r *segmentBufReader) Read(b []byte) (n int, err error) { func (r *segmentBufReader) Read(b []byte) (n int, err error) {
if len(r.segs) == 0 {
return 0, io.EOF
}
n, err = r.buf.Read(b) n, err = r.buf.Read(b)
r.off += n r.off += n