changeset 935:189ccb63b08b draft

Merge pull request #500 from gavinandresen/txndeadlock Fix AddAddress cs_mapaddresses/db transaction deadlock
author Gavin Andresen <gavinandresen@gmail.com>
date Wed, 07 Sep 2011 07:29:44 -0700
parents b85b74cbbad6 (current diff) a99cda147efc (diff)
children 4f02348aa51e faf2e7658d0c 7309d19d9ef3 e5d23800c530 bb5150a11d8b
files
diffstat 1 files changed, 21 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -443,6 +443,10 @@
     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 @@
             // 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 @@
                 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)