Skip to content

Commit 02464da

Browse files
committed
Merge #9227: Make nWalletDBUpdated atomic to avoid a potential race.
d63ff62 Make nWalletDBUpdated atomic to avoid a potential race. (Patrick Strateman)
2 parents 870cd2b + d63ff62 commit 02464da

File tree

5 files changed

+43
-33
lines changed

5 files changed

+43
-33
lines changed

src/wallet/db.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@
2424
using namespace std;
2525

2626

27-
unsigned int nWalletDBUpdated;
28-
29-
3027
//
3128
// CDB
3229
//

src/wallet/db.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100;
2424
static const bool DEFAULT_WALLET_PRIVDB = true;
2525

26-
extern unsigned int nWalletDBUpdated;
27-
2826
class CDBEnv
2927
{
3028
private:

src/wallet/wallet.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3691,7 +3691,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
36913691
walletInstance->ScanForWalletTransactions(pindexRescan, true);
36923692
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart);
36933693
walletInstance->SetBestChain(chainActive.GetLocator());
3694-
nWalletDBUpdated++;
3694+
CWalletDB::IncrementUpdateCounter();
36953695

36963696
// Restore wallet transaction metadata after -zapwallettxes=1
36973697
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")

src/wallet/walletdb.cpp

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include "utiltime.h"
1616
#include "wallet/wallet.h"
1717

18+
#include <atomic>
19+
1820
#include <boost/version.hpp>
1921
#include <boost/filesystem.hpp>
2022
#include <boost/foreach.hpp>
@@ -24,51 +26,53 @@ using namespace std;
2426

2527
static uint64_t nAccountingEntryNumber = 0;
2628

29+
static std::atomic<unsigned int> nWalletDBUpdateCounter;
30+
2731
//
2832
// CWalletDB
2933
//
3034

3135
bool CWalletDB::WriteName(const string& strAddress, const string& strName)
3236
{
33-
nWalletDBUpdated++;
37+
nWalletDBUpdateCounter++;
3438
return Write(make_pair(string("name"), strAddress), strName);
3539
}
3640

3741
bool CWalletDB::EraseName(const string& strAddress)
3842
{
3943
// This should only be used for sending addresses, never for receiving addresses,
4044
// receiving addresses must always have an address book entry if they're not change return.
41-
nWalletDBUpdated++;
45+
nWalletDBUpdateCounter++;
4246
return Erase(make_pair(string("name"), strAddress));
4347
}
4448

4549
bool CWalletDB::WritePurpose(const string& strAddress, const string& strPurpose)
4650
{
47-
nWalletDBUpdated++;
51+
nWalletDBUpdateCounter++;
4852
return Write(make_pair(string("purpose"), strAddress), strPurpose);
4953
}
5054

5155
bool CWalletDB::ErasePurpose(const string& strPurpose)
5256
{
53-
nWalletDBUpdated++;
57+
nWalletDBUpdateCounter++;
5458
return Erase(make_pair(string("purpose"), strPurpose));
5559
}
5660

5761
bool CWalletDB::WriteTx(const CWalletTx& wtx)
5862
{
59-
nWalletDBUpdated++;
63+
nWalletDBUpdateCounter++;
6064
return Write(std::make_pair(std::string("tx"), wtx.GetHash()), wtx);
6165
}
6266

6367
bool CWalletDB::EraseTx(uint256 hash)
6468
{
65-
nWalletDBUpdated++;
69+
nWalletDBUpdateCounter++;
6670
return Erase(std::make_pair(std::string("tx"), hash));
6771
}
6872

6973
bool CWalletDB::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta)
7074
{
71-
nWalletDBUpdated++;
75+
nWalletDBUpdateCounter++;
7276

7377
if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
7478
keyMeta, false))
@@ -88,7 +92,7 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
8892
const CKeyMetadata &keyMeta)
8993
{
9094
const bool fEraseUnencryptedKey = true;
91-
nWalletDBUpdated++;
95+
nWalletDBUpdateCounter++;
9296

9397
if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
9498
keyMeta))
@@ -106,31 +110,31 @@ bool CWalletDB::WriteCryptedKey(const CPubKey& vchPubKey,
106110

107111
bool CWalletDB::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey)
108112
{
109-
nWalletDBUpdated++;
113+
nWalletDBUpdateCounter++;
110114
return Write(std::make_pair(std::string("mkey"), nID), kMasterKey, true);
111115
}
112116

113117
bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript)
114118
{
115-
nWalletDBUpdated++;
119+
nWalletDBUpdateCounter++;
116120
return Write(std::make_pair(std::string("cscript"), hash), *(const CScriptBase*)(&redeemScript), false);
117121
}
118122

119123
bool CWalletDB::WriteWatchOnly(const CScript &dest)
120124
{
121-
nWalletDBUpdated++;
125+
nWalletDBUpdateCounter++;
122126
return Write(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)), '1');
123127
}
124128

125129
bool CWalletDB::EraseWatchOnly(const CScript &dest)
126130
{
127-
nWalletDBUpdated++;
131+
nWalletDBUpdateCounter++;
128132
return Erase(std::make_pair(std::string("watchs"), *(const CScriptBase*)(&dest)));
129133
}
130134

131135
bool CWalletDB::WriteBestBlock(const CBlockLocator& locator)
132136
{
133-
nWalletDBUpdated++;
137+
nWalletDBUpdateCounter++;
134138
Write(std::string("bestblock"), CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan
135139
return Write(std::string("bestblock_nomerkle"), locator);
136140
}
@@ -143,13 +147,13 @@ bool CWalletDB::ReadBestBlock(CBlockLocator& locator)
143147

144148
bool CWalletDB::WriteOrderPosNext(int64_t nOrderPosNext)
145149
{
146-
nWalletDBUpdated++;
150+
nWalletDBUpdateCounter++;
147151
return Write(std::string("orderposnext"), nOrderPosNext);
148152
}
149153

150154
bool CWalletDB::WriteDefaultKey(const CPubKey& vchPubKey)
151155
{
152-
nWalletDBUpdated++;
156+
nWalletDBUpdateCounter++;
153157
return Write(std::string("defaultkey"), vchPubKey);
154158
}
155159

@@ -160,13 +164,13 @@ bool CWalletDB::ReadPool(int64_t nPool, CKeyPool& keypool)
160164

161165
bool CWalletDB::WritePool(int64_t nPool, const CKeyPool& keypool)
162166
{
163-
nWalletDBUpdated++;
167+
nWalletDBUpdateCounter++;
164168
return Write(std::make_pair(std::string("pool"), nPool), keypool);
165169
}
166170

167171
bool CWalletDB::ErasePool(int64_t nPool)
168172
{
169-
nWalletDBUpdated++;
173+
nWalletDBUpdateCounter++;
170174
return Erase(std::make_pair(std::string("pool"), nPool));
171175
}
172176

@@ -780,20 +784,20 @@ void ThreadFlushWalletDB()
780784
if (!GetBoolArg("-flushwallet", DEFAULT_FLUSHWALLET))
781785
return;
782786

783-
unsigned int nLastSeen = nWalletDBUpdated;
784-
unsigned int nLastFlushed = nWalletDBUpdated;
787+
unsigned int nLastSeen = CWalletDB::GetUpdateCounter();
788+
unsigned int nLastFlushed = CWalletDB::GetUpdateCounter();
785789
int64_t nLastWalletUpdate = GetTime();
786790
while (true)
787791
{
788792
MilliSleep(500);
789793

790-
if (nLastSeen != nWalletDBUpdated)
794+
if (nLastSeen != CWalletDB::GetUpdateCounter())
791795
{
792-
nLastSeen = nWalletDBUpdated;
796+
nLastSeen = CWalletDB::GetUpdateCounter();
793797
nLastWalletUpdate = GetTime();
794798
}
795799

796-
if (nLastFlushed != nWalletDBUpdated && GetTime() - nLastWalletUpdate >= 2)
800+
if (nLastFlushed != CWalletDB::GetUpdateCounter() && GetTime() - nLastWalletUpdate >= 2)
797801
{
798802
TRY_LOCK(bitdb.cs_db,lockDb);
799803
if (lockDb)
@@ -815,7 +819,7 @@ void ThreadFlushWalletDB()
815819
if (_mi != bitdb.mapFileUseCount.end())
816820
{
817821
LogPrint("db", "Flushing %s\n", strFile);
818-
nLastFlushed = nWalletDBUpdated;
822+
nLastFlushed = CWalletDB::GetUpdateCounter();
819823
int64_t nStart = GetTimeMillis();
820824

821825
// Flush wallet file so it's self contained
@@ -922,19 +926,29 @@ bool CWalletDB::Recover(CDBEnv& dbenv, const std::string& filename)
922926

923927
bool CWalletDB::WriteDestData(const std::string &address, const std::string &key, const std::string &value)
924928
{
925-
nWalletDBUpdated++;
929+
nWalletDBUpdateCounter++;
926930
return Write(std::make_pair(std::string("destdata"), std::make_pair(address, key)), value);
927931
}
928932

929933
bool CWalletDB::EraseDestData(const std::string &address, const std::string &key)
930934
{
931-
nWalletDBUpdated++;
935+
nWalletDBUpdateCounter++;
932936
return Erase(std::make_pair(std::string("destdata"), std::make_pair(address, key)));
933937
}
934938

935939

936940
bool CWalletDB::WriteHDChain(const CHDChain& chain)
937941
{
938-
nWalletDBUpdated++;
942+
nWalletDBUpdateCounter++;
939943
return Write(std::string("hdchain"), chain);
940944
}
945+
946+
void CWalletDB::IncrementUpdateCounter()
947+
{
948+
nWalletDBUpdateCounter++;
949+
}
950+
951+
unsigned int CWalletDB::GetUpdateCounter()
952+
{
953+
return nWalletDBUpdateCounter;
954+
}

src/wallet/walletdb.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,11 @@ class CWalletDB : public CDB
176176
//! write the hdchain model (external chain child index counter)
177177
bool WriteHDChain(const CHDChain& chain);
178178

179+
static void IncrementUpdateCounter();
180+
static unsigned int GetUpdateCounter();
179181
private:
180182
CWalletDB(const CWalletDB&);
181183
void operator=(const CWalletDB&);
182-
183184
};
184185

185186
void ThreadFlushWalletDB();

0 commit comments

Comments
 (0)