aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWladimir J. van der Laan <[email protected]>2017-10-19 18:12:59 +0200
committerWladimir J. van der Laan <[email protected]>2017-10-19 18:16:46 +0200
commit99e93de6f8ab4fcaa244686bb047d184e74c3e27 (patch)
tree9537bcd85ca45299d363560f1a6dbb6847907919 /src
parentMerge #11527: Remove my testnet DNS seed as I currently don't have the capaci... (diff)
parentAvoid opening copied wallet databases simultaneously (diff)
downloaddiscoin-99e93de6f8ab4fcaa244686bb047d184e74c3e27.tar.xz
discoin-99e93de6f8ab4fcaa244686bb047d184e74c3e27.zip
Merge #11476: Avoid opening copied wallet databases simultaneously
478a89c Avoid opening copied wallet databases simultaneously (Russell Yanofsky) Pull request description: Make sure wallet databases have unique fileids. If they don't, throw an error. BDB caches do not work properly when more than one open database has the same fileid, because values written to one database may show up in reads to other databases. Bitcoin will never create different databases with the same fileid, but users can create them by manually copying database files. BDB caching bug was reported by @dooglus in https://github.com/bitcoin/bitcoin/issues/11429 Tree-SHA512: e7635dc81a181801f42324b72fe9e0a2a7dd00b1dcf5abcbf27fa50938eb9a1fc3065c2321326c3456c48c29ae6504353b02f3d46e6eb2f7b09e46d8fe24388d
Diffstat (limited to 'src')
-rw-r--r--src/wallet/db.cpp35
1 files changed, 35 insertions, 0 deletions
diff --git a/src/wallet/db.cpp b/src/wallet/db.cpp
index 5e881d9ac..459d289a4 100644
--- a/src/wallet/db.cpp
+++ b/src/wallet/db.cpp
@@ -20,6 +20,40 @@
#include <boost/thread.hpp>
+namespace {
+//! Make sure database has a unique fileid within the environment. If it
+//! doesn't, throw an error. BDB caches do not work properly when more than one
+//! open database has the same fileid (values written to one database may show
+//! up in reads to other databases).
+//!
+//! BerkeleyDB generates unique fileids by default
+//! (https://docs.oracle.com/cd/E17275_01/html/programmer_reference/program_copy.html),
+//! so bitcoin should never create different databases with the same fileid, but
+//! this error can be triggered if users manually copy database files.
+void CheckUniqueFileid(const CDBEnv& env, const std::string& filename, Db& db)
+{
+ if (env.IsMock()) return;
+
+ u_int8_t fileid[DB_FILE_ID_LEN];
+ int ret = db.get_mpf()->get_fileid(fileid);
+ if (ret != 0) {
+ throw std::runtime_error(strprintf("CDB: Can't open database %s (get_fileid failed with %d)", filename, ret));
+ }
+
+ for (const auto& item : env.mapDb) {
+ u_int8_t item_fileid[DB_FILE_ID_LEN];
+ if (item.second && item.second->get_mpf()->get_fileid(item_fileid) == 0 &&
+ memcmp(fileid, item_fileid, sizeof(fileid)) == 0) {
+ const char* item_filename = nullptr;
+ item.second->get_dbname(&item_filename, nullptr);
+ throw std::runtime_error(strprintf("CDB: Can't open database %s (duplicates fileid %s from %s)", filename,
+ HexStr(std::begin(item_fileid), std::end(item_fileid)),
+ item_filename ? item_filename : "(unknown database)"));
+ }
+ }
+}
+} // namespace
+
//
// CDB
//
@@ -403,6 +437,7 @@ CDB::CDB(CWalletDBWrapper& dbw, const char* pszMode, bool fFlushOnCloseIn) : pdb
if (ret != 0) {
throw std::runtime_error(strprintf("CDB: Error %d, can't open database %s", ret, strFilename));
}
+ CheckUniqueFileid(*env, strFilename, *pdb_temp);
pdb = pdb_temp.release();
env->mapDb[strFilename] = pdb;