From b52b6f2e3801fe14e09d646415cb798c565063d5 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 3 Jan 2012 01:28:15 +0100 Subject: Fix some address-handling deadlocks Made three critical blocks for cs_mapAddresses smaller, and moved writing to the database out of them. This should also improve the concurrency of the code. --- src/net.cpp | 59 +++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/net.cpp b/src/net.cpp index af59cee696..0f3b7cc863 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -496,21 +496,25 @@ bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB) void AddressCurrentlyConnected(const CAddress& addr) { + CAddress *paddrFound = NULL; + CRITICAL_BLOCK(cs_mapAddresses) { // Only if it's been published already map, CAddress>::iterator it = mapAddresses.find(addr.GetKey()); if (it != mapAddresses.end()) + paddrFound = &(*it).second; + } + + if (paddrFound) + { + int64 nUpdateInterval = 20 * 60; + if (paddrFound->nTime < GetAdjustedTime() - nUpdateInterval) { - CAddress& addrFound = (*it).second; - int64 nUpdateInterval = 20 * 60; - if (addrFound.nTime < GetAdjustedTime() - nUpdateInterval) - { - // Periodically update most recently seen time - addrFound.nTime = GetAdjustedTime(); - CAddrDB addrdb; - addrdb.WriteAddress(addrFound); - } + // Periodically update most recently seen time + paddrFound->nTime = GetAdjustedTime(); + CAddrDB addrdb; + addrdb.WriteAddress(*paddrFound); } } } @@ -1205,13 +1209,13 @@ void ThreadDNSAddressSeed2(void* parg) if (!fTestNet) { printf("Loading addresses from DNS seeds (could take a while)\n"); - CAddrDB addrDB; - addrDB.TxnBegin(); for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) { vector vaddr; if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true)) { + CAddrDB addrDB; + addrDB.TxnBegin(); BOOST_FOREACH (CAddress& addr, vaddr) { if (addr.GetByte(3) != 127) @@ -1221,10 +1225,9 @@ void ThreadDNSAddressSeed2(void* parg) found++; } } + addrDB.TxnCommit(); // Save addresses (it's ok if this fails) } } - - addrDB.TxnCommit(); // Save addresses (it's ok if this fails) } printf("%d addresses found from DNS seeds\n", found); @@ -1396,28 +1399,32 @@ void ThreadOpenConnections2(void* parg) if (fShutdown) return; + bool fAddSeeds = false; + CRITICAL_BLOCK(cs_mapAddresses) { // Add seed nodes if IRC isn't working bool fTOR = (fUseProxy && addrProxy.port == htons(9050)); if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet) + fAddSeeds = true; + } + + if (fAddSeeds) + { + for (int i = 0; i < ARRAYLEN(pnSeed); i++) { - for (int i = 0; i < ARRAYLEN(pnSeed); i++) - { - // It'll only connect to one or two seed nodes because once it connects, - // it'll get a pile of addresses with newer timestamps. - // Seed nodes are given a random 'last seen time' of between one and two - // weeks ago. - const int64 nOneWeek = 7*24*60*60; - CAddress addr; - addr.ip = pnSeed[i]; - addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek; - AddAddress(addr); - } + // It'll only connect to one or two seed nodes because once it connects, + // it'll get a pile of addresses with newer timestamps. + // Seed nodes are given a random 'last seen time' of between one and two + // weeks ago. + const int64 nOneWeek = 7*24*60*60; + CAddress addr; + addr.ip = pnSeed[i]; + addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek; + AddAddress(addr); } } - // // Choose an address to connect to based on most recently seen // -- cgit v1.2.3 From 84393f15b60ff5392da69b7cc208ffb5e8d209f0 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Tue, 3 Jan 2012 10:14:22 -0500 Subject: Fix issue #659, and cleanup wallet/command-line argument handling a bit Conflicts: src/init.cpp src/util.cpp --- src/init.cpp | 67 +++++++++++++++++++++++++++++++++++++----------------------- src/irc.cpp | 17 ++++----------- src/net.cpp | 2 +- src/util.cpp | 17 +++++++++++++++ src/util.h | 25 +++++++++++++++++++---- 5 files changed, 85 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/init.cpp b/src/init.cpp index 75ecfc574e..292424fb1d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -180,6 +180,7 @@ bool AppInit2(int argc, char* argv[]) " -maxconnections=\t " + _("Maintain at most connections to peers (default: 125)\n") + " -addnode= \t " + _("Add a node to connect to\n") + " -connect= \t\t " + _("Connect only to the specified node\n") + + " -noirc \t " + _("Don't find peers using internet relay chat\n") + " -nolisten \t " + _("Don't accept connections from outside\n") + " -nodnsseed \t " + _("Don't bootstrap list of peers using DNS\n") + " -maxreceivebuffer=\t " + _("Maximum per-connection receive buffer, *1000 bytes (default: 10000)\n") + @@ -237,7 +238,6 @@ bool AppInit2(int argc, char* argv[]) } fDebug = GetBoolArg("-debug"); - fAllowDNS = GetBoolArg("-dns"); #ifndef __WXMSW__ fDaemon = GetBoolArg("-daemon"); @@ -257,10 +257,6 @@ bool AppInit2(int argc, char* argv[]) fPrintToConsole = GetBoolArg("-printtoconsole"); fPrintToDebugger = GetBoolArg("-printtodebugger"); - - fTestNet = GetBoolArg("-testnet"); - bool fTOR = (fUseProxy && addrProxy.port == htons(9050)); - fNoListen = GetBoolArg("-nolisten") || fTOR; fLogTimestamps = GetBoolArg("-logtimestamps"); for (int i = 1; i < argc; i++) @@ -365,16 +361,7 @@ bool AppInit2(int argc, char* argv[]) return false; } - // Bind to the port early so we can tell if another instance is already running. string strErrors; - if (!fNoListen) - { - if (!BindListenPort(strErrors)) - { - wxMessageBox(strErrors, "Bitcoin"); - return false; - } - } // // Load data files @@ -456,6 +443,10 @@ bool AppInit2(int argc, char* argv[]) // Add wallet transactions that aren't already in a block to mapTransactions pwalletMain->ReacceptWalletTransactions(); + // Note: Bitcoin-QT stores several settings in the wallet, so we want + // to load the wallet BEFORE parsing command-line arguments, so + // the command-line/bitcoin.conf settings override GUI setting. + // // Parameters // @@ -508,6 +499,43 @@ bool AppInit2(int argc, char* argv[]) } } + fTestNet = GetBoolArg("-testnet"); + bool fTor = (fUseProxy && addrProxy.port == htons(9050)); + if (fTor) + { + // Use SoftSetArg here so user can override any of these if they wish. + // Note: the GetBoolArg() calls for all of these must happen later. + SoftSetArg("-nolisten", true); + SoftSetArg("-noirc", true); + SoftSetArg("-nodnsseed", true); + SoftSetArg("-noupnp", true); + SoftSetArg("-upnp", false); + SoftSetArg("-dns", false); + } + + fAllowDNS = GetBoolArg("-dns"); + fNoListen = GetBoolArg("-nolisten"); + + if (fHaveUPnP) + { +#if USE_UPNP + if (GetBoolArg("-noupnp")) + fUseUPnP = false; +#else + if (GetBoolArg("-upnp")) + fUseUPnP = true; +#endif + } + + if (!fNoListen) + { + if (!BindListenPort(strErrors)) + { + wxMessageBox(strErrors, "Bitcoin"); + return false; + } + } + if (mapArgs.count("-addnode")) { BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"]) @@ -530,17 +558,6 @@ bool AppInit2(int argc, char* argv[]) wxMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), "Bitcoin", wxOK | wxICON_EXCLAMATION); } - if (fHaveUPnP) - { -#if USE_UPNP - if (GetBoolArg("-noupnp")) - fUseUPnP = false; -#else - if (GetBoolArg("-upnp")) - fUseUPnP = true; -#endif - } - // // Create the main window and start the node // diff --git a/src/irc.cpp b/src/irc.cpp index 5278488dcd..fe96a90a1c 100644 --- a/src/irc.cpp +++ b/src/irc.cpp @@ -264,19 +264,14 @@ void ThreadIRCSeed2(void* parg) int nErrorWait = 10; int nRetryWait = 10; bool fNameInUse = false; - bool fTOR = (fUseProxy && addrProxy.port == htons(9050)); while (!fShutdown) { - //CAddress addrConnect("216.155.130.130:6667"); // chat.freenode.net CAddress addrConnect("92.243.23.21", 6667); // irc.lfnet.org - if (!fTOR) - { - //struct hostent* phostent = gethostbyname("chat.freenode.net"); - CAddress addrIRC("irc.lfnet.org", 6667, true); - if (addrIRC.IsValid()) - addrConnect = addrIRC; - } + + CAddress addrIRC("irc.lfnet.org", 6667, true); + if (addrIRC.IsValid()) + addrConnect = addrIRC; SOCKET hSocket; if (!ConnectSocket(addrConnect, hSocket)) @@ -406,10 +401,6 @@ void ThreadIRCSeed2(void* parg) closesocket(hSocket); hSocket = INVALID_SOCKET; - // IRC usually blocks TOR, so only try once - if (fTOR) - return; - if (GetTime() - nStart > 20 * 60) { nErrorWait /= 3; diff --git a/src/net.cpp b/src/net.cpp index 0f3b7cc863..c7475b118c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1405,7 +1405,7 @@ void ThreadOpenConnections2(void* parg) { // Add seed nodes if IRC isn't working bool fTOR = (fUseProxy && addrProxy.port == htons(9050)); - if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet) + if (mapAddresses.empty() && (GetTime() - nStart > 60 || fUseProxy) && !fTestNet) fAddSeeds = true; } diff --git a/src/util.cpp b/src/util.cpp index d6a113095d..a3f1c9507d 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -472,6 +472,23 @@ void ParseParameters(int argc, char* argv[]) } } +bool SoftSetArg(const std::string& strArg, const std::string& strValue) +{ + if (mapArgs.count(strArg)) + return false; + mapArgs[strArg] = strValue; + return true; +} + +bool SoftSetArg(const std::string& strArg, bool fValue) +{ + if (fValue) + return SoftSetArg(strArg, std::string("1")); + else + return SoftSetArg(strArg, std::string("0")); +} + + const char* wxGetTranslation(const char* pszEnglish) { diff --git a/src/util.h b/src/util.h index 6ecc92b2b6..9f9001e06e 100644 --- a/src/util.h +++ b/src/util.h @@ -442,7 +442,7 @@ inline int64 GetArg(const std::string& strArg, int64 nDefault) return nDefault; } -inline bool GetBoolArg(const std::string& strArg) +inline bool GetBoolArg(const std::string& strArg, bool fDefault=false) { if (mapArgs.count(strArg)) { @@ -450,9 +450,26 @@ inline bool GetBoolArg(const std::string& strArg) return true; return (atoi(mapArgs[strArg]) != 0); } - return false; -} - + return fDefault; +} + +/** + * Set an argument if it doesn't already have a value + * + * @param strArg Argument to set (e.g. "-foo") + * @param strValue Value (e.g. "1") + * @return true if argument gets set, false if it already had a value + */ +bool SoftSetArg(const std::string& strArg, const std::string& strValue); + +/** + * Set a boolean argument if it doesn't already have a value + * + * @param strArg Argument to set (e.g. "-foo") + * @param fValue Value (e.g. false) + * @return true if argument gets set, false if it already had a value + */ +bool SoftSetArg(const std::string& strArg, bool fValue); -- cgit v1.2.3 From cc6bd19660461091903568803014b39d571fd458 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Tue, 3 Jan 2012 11:17:04 -0500 Subject: I broke -testnet with my TOR option-parsing fixes. --- src/init.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/init.cpp b/src/init.cpp index 292424fb1d..d1332e0610 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -237,6 +237,7 @@ bool AppInit2(int argc, char* argv[]) return false; } + fTestNet = GetBoolArg("-testnet"); fDebug = GetBoolArg("-debug"); #ifndef __WXMSW__ @@ -499,7 +500,6 @@ bool AppInit2(int argc, char* argv[]) } } - fTestNet = GetBoolArg("-testnet"); bool fTor = (fUseProxy && addrProxy.port == htons(9050)); if (fTor) { -- cgit v1.2.3