wallet: bugfix, GetNewCursor() misses to provide batch ptr to BerkeleyCursor

If the batch ptr is not passed, the cursor will not use the db active
txn context which could lead to a deadlock if the code tries to modify
the db while it is traversing it.

E.g. the 'EraseRecords()' function.
This commit is contained in:
furszy 2023-05-01 10:21:36 -03:00
parent d7700d3a26
commit 043fcb0b05
No known key found for this signature in database
GPG key ID: 5DD23CCC686AA623
2 changed files with 5 additions and 5 deletions

View file

@ -668,14 +668,14 @@ void BerkeleyDatabase::ReloadDbEnv()
env->ReloadDbEnv();
}
BerkeleyCursor::BerkeleyCursor(BerkeleyDatabase& database, BerkeleyBatch* batch)
BerkeleyCursor::BerkeleyCursor(BerkeleyDatabase& database, const BerkeleyBatch& batch)
{
if (!database.m_db.get()) {
throw std::runtime_error(STR_INTERNAL_BUG("BerkeleyDatabase does not exist"));
}
// Transaction argument to cursor is only needed when using the cursor to
// write to the database. Read-only cursors do not need a txn pointer.
int ret = database.m_db->cursor(batch ? batch->txn() : nullptr, &m_cursor, 0);
int ret = database.m_db->cursor(batch.txn(), &m_cursor, 0);
if (ret != 0) {
throw std::runtime_error(STR_INTERNAL_BUG(strprintf("BDB Cursor could not be created. Returned %d", ret)));
}
@ -713,7 +713,7 @@ BerkeleyCursor::~BerkeleyCursor()
std::unique_ptr<DatabaseCursor> BerkeleyBatch::GetNewCursor()
{
if (!pdb) return nullptr;
return std::make_unique<BerkeleyCursor>(m_database);
return std::make_unique<BerkeleyCursor>(m_database, *this);
}
bool BerkeleyBatch::TxnBegin()
@ -825,7 +825,7 @@ bool BerkeleyBatch::HasKey(DataStream&& key)
bool BerkeleyBatch::ErasePrefix(Span<const std::byte> prefix)
{
if (!TxnBegin()) return false;
auto cursor{std::make_unique<BerkeleyCursor>(m_database, this)};
auto cursor{std::make_unique<BerkeleyCursor>(m_database, *this)};
// const_cast is safe below even though prefix_key is an in/out parameter,
// because we are not using the DB_DBT_USERMEM flag, so BDB will allocate
// and return a different output data pointer

View file

@ -192,7 +192,7 @@ private:
Dbc* m_cursor;
public:
explicit BerkeleyCursor(BerkeleyDatabase& database, BerkeleyBatch* batch=nullptr);
explicit BerkeleyCursor(BerkeleyDatabase& database, const BerkeleyBatch& batch);
~BerkeleyCursor() override;
Status Next(DataStream& key, DataStream& value) override;