Check return value of TableBuilder::Add() in compaction routine.

This is a prospective fix for the crash described in
crbug.com/326566884. Inspection of the crash dump suggests that
`Add()` is failing, but the compaction routine is continuing to
run. While it's not entirely clear how precisely this leads to
the observed failure mode, it seems safer to check the status
of the TableBuilder and abort early as needed.
This commit is contained in:
Evan Stade 2024-04-09 21:52:52 +00:00
parent 068d5ee1a3
commit 80d6c09fa4
3 changed files with 12 additions and 4 deletions

View File

@ -998,7 +998,12 @@ Status DBImpl::DoCompactionWork(CompactionState* compact) {
compact->current_output()->smallest.DecodeFrom(key); compact->current_output()->smallest.DecodeFrom(key);
} }
compact->current_output()->largest.DecodeFrom(key); compact->current_output()->largest.DecodeFrom(key);
compact->builder->Add(key, input->value());
status = compact->builder->Add(key, input->value());
if (!status.ok()) {
FinishCompactionOutputFile(compact, input);
break;
}
// Close output file if it is big enough // Close output file if it is big enough
if (compact->builder->FileSize() >= if (compact->builder->FileSize() >=

View File

@ -49,7 +49,7 @@ class LEVELDB_EXPORT TableBuilder {
// Add key,value to the table being constructed. // Add key,value to the table being constructed.
// REQUIRES: key is after any previously added key according to comparator. // REQUIRES: key is after any previously added key according to comparator.
// REQUIRES: Finish(), Abandon() have not been called // REQUIRES: Finish(), Abandon() have not been called
void Add(const Slice& key, const Slice& value); Status Add(const Slice& key, const Slice& value);
// Advanced operation: flush any buffered key/value pairs to file. // Advanced operation: flush any buffered key/value pairs to file.
// Can be used to ensure that two adjacent entries never live in // Can be used to ensure that two adjacent entries never live in

View File

@ -91,10 +91,12 @@ Status TableBuilder::ChangeOptions(const Options& options) {
return Status::OK(); return Status::OK();
} }
void TableBuilder::Add(const Slice& key, const Slice& value) { Status TableBuilder::Add(const Slice& key, const Slice& value) {
Rep* r = rep_; Rep* r = rep_;
assert(!r->closed); assert(!r->closed);
if (!ok()) return; if (!ok()) {
return status();
}
if (r->num_entries > 0) { if (r->num_entries > 0) {
assert(r->options.comparator->Compare(key, Slice(r->last_key)) > 0); assert(r->options.comparator->Compare(key, Slice(r->last_key)) > 0);
} }
@ -120,6 +122,7 @@ void TableBuilder::Add(const Slice& key, const Slice& value) {
if (estimated_block_size >= r->options.block_size) { if (estimated_block_size >= r->options.block_size) {
Flush(); Flush();
} }
return status();
} }
void TableBuilder::Flush() { void TableBuilder::Flush() {