diff --git a/src/wallet/bdb.cpp b/src/wallet/bdb.cpp --- a/src/wallet/bdb.cpp +++ b/src/wallet/bdb.cpp @@ -33,17 +33,19 @@ int ret = db.get_mpf()->get_fileid(fileid.value); if (ret != 0) { - throw std::runtime_error(strprintf( - "BerkeleyBatch: Can't open database %s (get_fileid failed with %d)", - filename, ret)); + throw std::runtime_error( + strprintf("BerkeleyDatabase: Can't open database %s (get_fileid " + "failed with %d)", + filename, ret)); } for (const auto &item : env.m_fileids) { if (fileid == item.second && &fileid != &item.second) { - throw std::runtime_error(strprintf( - "BerkeleyBatch: Can't open database %s (duplicates fileid %s " - "from %s)", - filename, HexStr(item.second.value), item.first)); + throw std::runtime_error( + strprintf("BerkeleyDatabase: Can't open database %s " + "(duplicates fileid %s " + "from %s)", + filename, HexStr(item.second.value), item.first)); } } } @@ -331,6 +333,8 @@ BerkeleyDatabase::~BerkeleyDatabase() { if (env) { LOCK(cs_db); + env->CloseDb(strFile); + assert(!m_db); size_t erased = env->m_databases.erase(strFile); assert(erased == 1); env->m_fileids.erase(strFile); @@ -406,26 +410,13 @@ "BerkeleyDatabase: Error %d, can't open database %s", ret, strFile)); } + m_file_path = (env->Directory() / strFile).string(); // Call CheckUniqueFileid on the containing BDB environment to // avoid BDB data consistency bugs that happen when different data // files in the same environment have the same fileid. - // - // Also call CheckUniqueFileid on all the other g_dbenvs to prevent - // bitcoin from opening the same data file through another - // environment when the file is referenced through equivalent but - // not obviously identical symlinked or hard linked or bind mounted - // paths. In the future a more relaxed check for equal inode and - // device ids could be done instead, which would allow opening - // different backup copies of a wallet at the same time. Maybe even - // more ideally, an exclusive lock for accessing the database could - // be implemented, so no equality checks are needed at all. (Newer - // versions of BDB have an set_lk_exclusive method for this - // purpose, but the older version we use does not.) - for (const auto &dbenv : g_dbenvs) { - CheckUniqueFileid(*dbenv.second.lock().get(), strFile, - *pdb_temp, this->env->m_fileids[strFile]); - } + CheckUniqueFileid(*env, strFile, *pdb_temp, + this->env->m_fileids[strFile]); m_db.reset(pdb_temp.release()); } diff --git a/test/functional/wallet_multiwallet.py b/test/functional/wallet_multiwallet.py --- a/test/functional/wallet_multiwallet.py +++ b/test/functional/wallet_multiwallet.py @@ -138,7 +138,7 @@ # should not initialize if one wallet is a copy of another shutil.copyfile(wallet_dir('w8'), wallet_dir('w8_copy')) - exp_stderr = r"BerkeleyBatch: Can't open database w8_copy \(duplicates fileid \w+ from w8\)" + exp_stderr = r"BerkeleyDatabase: Can't open database w8_copy \(duplicates fileid \w+ from w8\)" self.nodes[0].assert_start_raises_init_error( ['-wallet=w8', '-wallet=w8_copy'], exp_stderr, match=ErrorMatch.PARTIAL_REGEX) @@ -317,13 +317,13 @@ 'wallet.dat') # Fail to load if one wallet is a copy of another - assert_raises_rpc_error(-4, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", + assert_raises_rpc_error(-4, "BerkeleyDatabase: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy') # Fail to load if one wallet is a copy of another. # Test this twice to make sure that we don't re-introduce # https://github.com/bitcoin/bitcoin/issues/14304 - assert_raises_rpc_error(-4, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", + assert_raises_rpc_error(-4, "BerkeleyDatabase: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy') # Fail to load if wallet file is a symlink