aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2011-09-06 13:39:17 -0400
committerGavin Andresen <gavinandresen@gmail.com>2011-09-06 20:28:15 -0400
commit940669657837e4a247a4d0746c12f52e8662f325 (patch)
treec4466c2ac1334eba4c4535d49d61f114050bb081
parente39f9256550e3e30965d1d5e6e16d232c3e0e4ac (diff)
downloadbitcoin-940669657837e4a247a4d0746c12f52e8662f325.tar.xz
Fix AddAddress cs_mapaddresses/db transaction deadlock
-rw-r--r--src/net.cpp36
1 files changed, 21 insertions, 15 deletions
diff --git a/src/net.cpp b/src/net.cpp
index 5fca17aa46..509d8905f9 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -443,6 +443,10 @@ bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
if (addr.ip == addrLocalHost.ip)
return false;
addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
+ bool fUpdated = false;
+ bool fNew = false;
+ CAddress addrFound = addr;
+
CRITICAL_BLOCK(cs_mapAddresses)
{
map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
@@ -451,16 +455,12 @@ bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
// New address
printf("AddAddress(%s)\n", addr.ToString().c_str());
mapAddresses.insert(make_pair(addr.GetKey(), addr));
- if (pAddrDB)
- pAddrDB->WriteAddress(addr);
- else
- CAddrDB().WriteAddress(addr);
- return true;
+ fUpdated = true;
+ fNew = true;
}
else
{
- bool fUpdated = false;
- CAddress& addrFound = (*it).second;
+ addrFound = (*it).second;
if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
{
// Services have been added
@@ -475,16 +475,22 @@ bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
addrFound.nTime = addr.nTime;
fUpdated = true;
}
- if (fUpdated)
- {
- if (pAddrDB)
- pAddrDB->WriteAddress(addrFound);
- else
- CAddrDB().WriteAddress(addrFound);
- }
}
}
- return false;
+ // There is a nasty deadlock bug if this is done inside the cs_mapAddresses
+ // CRITICAL_BLOCK:
+ // Thread 1: begin db transaction (locks inside-db-mutex)
+ // then AddAddress (locks cs_mapAddresses)
+ // Thread 2: AddAddress (locks cs_mapAddresses)
+ // ... then db operation hangs waiting for inside-db-mutex
+ if (fUpdated)
+ {
+ if (pAddrDB)
+ pAddrDB->WriteAddress(addrFound);
+ else
+ CAddrDB().WriteAddress(addrFound);
+ }
+ return fNew;
}
void AddressCurrentlyConnected(const CAddress& addr)