From b31499ec72edd1554d4612d1b54808fce0360e14 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Sat, 9 Mar 2013 12:02:57 -0500 Subject: [PATCH] Clean up shutdown process --- src/bitcoinrpc.cpp | 12 ++- src/db.cpp | 8 +- src/db.h | 2 +- src/init.cpp | 195 ++++++++++++++++++++++----------------------- src/init.h | 3 +- src/main.cpp | 29 ++++--- src/net.cpp | 35 +++----- src/net.h | 9 +-- src/qt/bitcoin.cpp | 2 +- src/txdb.cpp | 6 +- src/util.cpp | 2 - src/util.h | 2 - src/wallet.cpp | 1 - src/wallet.h | 3 +- src/walletdb.cpp | 16 ++-- 15 files changed, 147 insertions(+), 178 deletions(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 53b363575..9c126fc3d 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -1221,13 +1221,14 @@ int CommandLineRPC(int argc, char *argv[]) strPrint = write_string(result, true); } } - catch (std::exception& e) - { + catch (boost::thread_interrupted) { + throw; + } + catch (std::exception& e) { strPrint = string("error: ") + e.what(); nRet = 87; } - catch (...) - { + catch (...) { PrintException(NULL, "CommandLineRPC()"); } @@ -1265,6 +1266,9 @@ int main(int argc, char *argv[]) return CommandLineRPC(argc, argv); } } + catch (boost::thread_interrupted) { + throw; + } catch (std::exception& e) { PrintException(&e, "main()"); } catch (...) { diff --git a/src/db.cpp b/src/db.cpp index 87c4b5c7e..35d6cca89 100644 --- a/src/db.cpp +++ b/src/db.cpp @@ -62,8 +62,7 @@ bool CDBEnv::Open(const boost::filesystem::path& path) if (fDbEnvInit) return true; - if (fShutdown) - return false; + boost::this_thread::interruption_point(); strPath = path.string(); filesystem::path pathLogDir = path / "database"; @@ -108,8 +107,7 @@ void CDBEnv::MakeMock() if (fDbEnvInit) throw runtime_error("CDBEnv::MakeMock(): already initialized"); - if (fShutdown) - throw runtime_error("CDBEnv::MakeMock(): during shutdown"); + boost::this_thread::interruption_point(); printf("CDBEnv::MakeMock()\n"); @@ -327,7 +325,7 @@ bool CDBEnv::RemoveDb(const string& strFile) bool CDB::Rewrite(const string& strFile, const char* pszSkip) { - while (!fShutdown) + while (true) { { LOCK(bitdb.cs_db); diff --git a/src/db.h b/src/db.h index 9c01060a1..206da91e9 100644 --- a/src/db.h +++ b/src/db.h @@ -24,7 +24,7 @@ class CWalletTx; extern unsigned int nWalletDBUpdated; -void ThreadFlushWalletDB(void* parg); +void ThreadFlushWalletDB(const std::string& strWalletFile); bool BackupWallet(const CWallet& wallet, const std::string& strDest); diff --git a/src/init.cpp b/src/init.cpp index a2e85f2ef..3ccd01e3b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -40,75 +40,65 @@ enum BindFlags { // Shutdown // -void ExitTimeout(void* parg) -{ -#ifdef WIN32 - MilliSleep(5000); - ExitProcess(0); -#endif -} +// +// Thread management and startup/shutdown: +// +// The network-processing threads are all part of a thread group +// created by AppInit() or the Qt main() function. +// +// A clean exit happens when StartShutdown() or the SIGTERM +// signal handler sets fRequestShutdown, which triggers +// the DetectShutdownThread(), which interrupts the main thread group. +// DetectShutdownThread() then exits, which causes AppInit() to +// continue (it .joins the shutdown thread). +// Shutdown() is then +// called to clean up database connections, and stop other +// threads that should only be stopped after the main network-processing +// threads have exited. +// +// Note that if running -daemon the parent process returns from AppInit2 +// before adding any threads to the threadGroup, so .join_all() returns +// immediately and the parent exits from main(). +// +// Shutdown for Qt is very similar, only it uses a QTimer to detect +// fRequestShutdown getting set (either by RPC stop or SIGTERM) +// and then does the normal Qt shutdown thing. +// + +volatile bool fRequestShutdown = false; void StartShutdown() { -#ifdef QT_GUI - // ensure we leave the Qt main loop for a clean GUI exit (Shutdown() is called in bitcoin.cpp afterwards) - uiInterface.QueueShutdown(); -#else - // Without UI, Shutdown() can simply be started in a new thread - NewThread(Shutdown, NULL); -#endif + fRequestShutdown = true; } static CCoinsViewDB *pcoinsdbview; -void Shutdown(void* parg) +void Shutdown() { static CCriticalSection cs_Shutdown; - static bool fTaken; + TRY_LOCK(cs_Shutdown, lockShutdown); + if (!lockShutdown) return; - // Make this thread recognisable as the shutdown thread RenameThread("bitcoin-shutoff"); nTransactionsUpdated++; StopRPCThreads(); bitdb.Flush(false); StopNode(); { - fShutdown = true; - fRequestShutdown = true; - nTransactionsUpdated++; - StopRPCThreads(); - bitdb.Flush(false); - StopNode(); - { - LOCK(cs_main); - if (pblocktree) - pblocktree->Flush(); - if (pcoinsTip) - pcoinsTip->Flush(); - delete pcoinsTip; - delete pcoinsdbview; - delete pblocktree; - } - bitdb.Flush(true); - boost::filesystem::remove(GetPidFile()); - UnregisterWallet(pwalletMain); - delete pwalletMain; - NewThread(ExitTimeout, NULL); - MilliSleep(50); - printf("Bitcoin exited\n\n"); - fExit = true; -#ifndef QT_GUI - // ensure non-UI client gets exited here, but let Bitcoin-Qt reach 'return 0;' in bitcoin.cpp - exit(0); -#endif - } - else - { - while (!fExit) - MilliSleep(500); - MilliSleep(100); - ExitThread(0); + LOCK(cs_main); + if (pblocktree) + pblocktree->Flush(); + if (pcoinsTip) + pcoinsTip->Flush(); + delete pcoinsTip; pcoinsTip = NULL; + delete pcoinsdbview; pcoinsdbview = NULL; + delete pblocktree; pblocktree = NULL; } + bitdb.Flush(true); + boost::filesystem::remove(GetPidFile()); + UnregisterWallet(pwalletMain); + delete pwalletMain; } // @@ -116,9 +106,13 @@ void Shutdown(void* parg) // void DetectShutdownThread(boost::thread_group* threadGroup) { - while (fRequestShutdown == false) + // Tell the main threads to shutdown. + while (!fRequestShutdown) + { MilliSleep(200); - threadGroup->interrupt_all(); + if (fRequestShutdown) + threadGroup->interrupt_all(); + } } void HandleSIGTERM(int) @@ -143,6 +137,8 @@ void HandleSIGHUP(int) bool AppInit(int argc, char* argv[]) { boost::thread_group threadGroup; + boost::thread* detectShutdownThread = NULL; + bool fRet = false; try { @@ -154,7 +150,7 @@ bool AppInit(int argc, char* argv[]) if (!boost::filesystem::is_directory(GetDataDir(false))) { fprintf(stderr, "Error: Specified directory does not exist\n"); - Shutdown(NULL); + Shutdown(); } ReadConfigFile(mapArgs, mapMultiArgs); @@ -184,7 +180,31 @@ bool AppInit(int argc, char* argv[]) int ret = CommandLineRPC(argc, argv); exit(ret); } +#if !defined(WIN32) + fDaemon = GetBoolArg("-daemon"); + if (fDaemon) + { + // Daemonize + pid_t pid = fork(); + if (pid < 0) + { + fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno); + return false; + } + if (pid > 0) // Parent process, pid is child process id + { + CreatePidFile(GetPidFile(), pid); + return true; + } + // Child process falls through to rest of initialization + pid_t sid = setsid(); + if (sid < 0) + fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno); + } +#endif + + detectShutdownThread = new boost::thread(boost::bind(&DetectShutdownThread, &threadGroup)); fRet = AppInit2(threadGroup); } catch (std::exception& e) { @@ -192,12 +212,20 @@ bool AppInit(int argc, char* argv[]) } catch (...) { PrintExceptionContinue(NULL, "AppInit()"); } - if (!fRet) - { - Shutdown(NULL); - threadGroup.interrupt_all(); - threadGroup.join_all(); + if (!fRet) { + if (detectShutdownThread) + detectShutdownThread->interrupt(); + threadGroup.interrupt_all(); } + + if (detectShutdownThread) + { + detectShutdownThread->join(); + delete detectShutdownThread; + detectShutdownThread = NULL; + } + Shutdown(); + return fRet; } @@ -214,7 +242,7 @@ int main(int argc, char* argv[]) if (fRet && fDaemon) return 0; - return 1; + return (fRet ? 0 : 1); } #endif @@ -302,7 +330,7 @@ std::string HelpMessage() " -rpcport= " + _("Listen for JSON-RPC connections on (default: 8332 or testnet: 18332)") + "\n" + " -rpcallowip= " + _("Allow JSON-RPC connections from specified IP address") + "\n" + " -rpcconnect= " + _("Send commands to node running on (default: 127.0.0.1)") + "\n" + - " -rpcthreads= " + _("Use this mean threads to service RPC calls (default: 4)") + "\n" + + " -rpcthreads= " + _("Use this many threads to service RPC calls (default: 4)") + "\n" + " -blocknotify= " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n" + " -walletnotify= " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n" + " -alertnotify= " + _("Execute command when a relevant alert is received (%s in cmd is replaced by message)") + "\n" + @@ -440,8 +468,6 @@ bool AppInit2(boost::thread_group& threadGroup) sigaction(SIGHUP, &sa_hup, NULL); #endif - threadGroup.create_thread(boost::bind(&DetectShutdownThread, &threadGroup)); - // ********************************************************* Step 2: parameter interactions fTestNet = GetBoolArg("-testnet"); @@ -499,12 +525,6 @@ bool AppInit2(boost::thread_group& threadGroup) else fDebugNet = GetBoolArg("-debugnet"); -#if !defined(WIN32) && !defined(QT_GUI) - fDaemon = GetBoolArg("-daemon"); -#else - fDaemon = false; -#endif - if (fDaemon) fServer = true; else @@ -552,28 +572,6 @@ bool AppInit2(boost::thread_group& threadGroup) if (!lock.try_lock()) return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), strDataDir.c_str())); -#if !defined(WIN32) && !defined(QT_GUI) - if (fDaemon) - { - // Daemonize - pid_t pid = fork(); - if (pid < 0) - { - fprintf(stderr, "Error: fork() returned %d errno %d\n", pid, errno); - return false; - } - if (pid > 0) - { - CreatePidFile(GetPidFile(), pid); - return true; - } - - pid_t sid = setsid(); - if (sid < 0) - fprintf(stderr, "Error: setsid() returned %d errno %d\n", sid, errno); - } -#endif - if (GetBoolArg("-shrinkdebugfile", !fDebug)) ShrinkDebugFile(); printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); @@ -1011,8 +1009,7 @@ bool AppInit2(boost::thread_group& threadGroup) printf("mapWallet.size() = %"PRIszu"\n", pwalletMain->mapWallet.size()); printf("mapAddressBook.size() = %"PRIszu"\n", pwalletMain->mapAddressBook.size()); - if (!NewThread(StartNode, (void*)&threadGroup)) - InitError(_("Error: could not start node")); + StartNode(threadGroup); if (fServer) StartRPCThreads(); @@ -1030,12 +1027,8 @@ bool AppInit2(boost::thread_group& threadGroup) // Add wallet transactions that aren't already in a block to mapTransactions pwalletMain->ReacceptWalletTransactions(); -#if !defined(QT_GUI) - // Loop until process is exit()ed from shutdown() function, - // called from ThreadRPCServer thread when a "stop" command is received. - while (1) - MilliSleep(5000); -#endif + // Run a thread to flush wallet periodically + threadGroup.create_thread(boost::bind(&ThreadFlushWalletDB, boost::ref(pwalletMain->strWalletFile))); - return true; + return !fRequestShutdown; } diff --git a/src/init.h b/src/init.h index 8986ff620..2968ca561 100644 --- a/src/init.h +++ b/src/init.h @@ -7,11 +7,10 @@ #include "wallet.h" -class boost::thread_group; extern CWallet* pwalletMain; void StartShutdown(); -void Shutdown(void* parg); +void Shutdown(); bool AppInit2(boost::thread_group& threadGroup); std::string HelpMessage(); diff --git a/src/main.cpp b/src/main.cpp index 39a291d07..57a4df085 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1256,8 +1256,7 @@ bool ConnectBestBlock(CValidationState &state) { if (pindexTest->pprev == NULL || pindexTest->pnext != NULL) { reverse(vAttach.begin(), vAttach.end()); BOOST_FOREACH(CBlockIndex *pindexSwitch, vAttach) { - if (fRequestShutdown) - break; + boost::this_thread::interruption_point(); try { if (!SetBestChain(state, pindexSwitch)) return false; @@ -2457,7 +2456,6 @@ uint256 CPartialMerkleTree::ExtractMatches(std::vector &vMatch) { bool AbortNode(const std::string &strMessage) { - fRequestShutdown = true; strMiscWarning = strMessage; printf("*** %s\n", strMessage.c_str()); uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_ERROR); @@ -2536,8 +2534,7 @@ bool static LoadBlockIndexDB() if (!pblocktree->LoadBlockIndexGuts()) return false; - if (fRequestShutdown) - return true; + boost::this_thread::interruption_point(); // Calculate bnChainWork vector > vSortedByHeight; @@ -2617,7 +2614,8 @@ bool VerifyDB() { CValidationState state; for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev) { - if (fRequestShutdown || pindex->nHeight < nBestHeight-nCheckDepth) + boost::this_thread::interruption_point(); + if (pindex->nHeight < nBestHeight-nCheckDepth) break; CBlock block; // check level 0: read from disk @@ -2654,7 +2652,8 @@ bool VerifyDB() { // check level 4: try reconnecting blocks if (nCheckLevel >= 4) { CBlockIndex *pindex = pindexState; - while (pindex != pindexBest && !fRequestShutdown) { + while (pindex != pindexBest) { + boost::this_thread::interruption_point(); pindex = pindex->pnext; CBlock block; if (!block.ReadFromDisk(pindex)) @@ -3038,8 +3037,7 @@ void static ProcessGetData(CNode* pfrom) const CInv &inv = *it; { - if (fShutdown) - break; + boost::this_thread::interruption_point(); it++; if (inv.type == MSG_BLOCK || inv.type == MSG_FILTERED_BLOCK) @@ -3297,8 +3295,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) int64 nSince = nNow - 10 * 60; BOOST_FOREACH(CAddress& addr, vAddr) { - if (fShutdown) - return true; + boost::this_thread::interruption_point(); + if (addr.nTime <= 100000000 || addr.nTime > nNow + 10 * 60) addr.nTime = nNow - 5 * 24 * 60 * 60; pfrom->AddAddressKnown(addr); @@ -3366,8 +3364,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) { const CInv &inv = vInv[nInv]; - if (fShutdown) - return true; + boost::this_thread::interruption_point(); pfrom->AddInventoryKnown(inv); bool fAlreadyHave = AlreadyHave(inv); @@ -3799,8 +3796,7 @@ bool ProcessMessages(CNode* pfrom) LOCK(cs_main); fRet = ProcessMessage(pfrom, strCommand, vRecv); } - if (fShutdown) - break; + boost::this_thread::interruption_point(); } catch (std::ios_base::failure& e) { @@ -3819,6 +3815,9 @@ bool ProcessMessages(CNode* pfrom) PrintExceptionContinue(&e, "ProcessMessages()"); } } + catch (boost::thread_interrupted) { + throw; + } catch (std::exception& e) { PrintExceptionContinue(&e, "ProcessMessages()"); } catch (...) { diff --git a/src/net.cpp b/src/net.cpp index 557bd6f87..f1ece2c2e 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -45,7 +45,6 @@ static bool vfReachable[NET_MAX] = {}; static bool vfLimited[NET_MAX] = {}; static CNode* pnodeLocalHost = NULL; uint64 nLocalHostNonce = 0; -array vnThreadsRunning; static std::vector vhListenSocket; CAddrMan addrman; @@ -147,8 +146,7 @@ bool RecvLine(SOCKET hSocket, string& strLine) } else if (nBytes <= 0) { - if (fShutdown) - return false; + boost::this_thread::interruption_point(); if (nBytes < 0) { int nErr = WSAGetLastError(); @@ -1775,10 +1773,8 @@ void static Discover() NewThread(ThreadGetMyExternalIP, NULL); } -void StartNode(void* parg) +void StartNode(boost::thread_group& threadGroup) { - boost::thread_group* threadGroup = (boost::thread_group*)parg; - // Make this thread recognisable as the startup thread RenameThread("bitcoin-start"); @@ -1800,25 +1796,27 @@ void StartNode(void* parg) if (!GetBoolArg("-dnsseed", true)) printf("DNS seeding disabled\n"); else - threadGroup->create_thread(boost::bind(&TraceThread >, "dnsseed", &ThreadDNSAddressSeed)); + threadGroup.create_thread(boost::bind(&TraceThread >, "dnsseed", &ThreadDNSAddressSeed)); +#ifdef USE_UPNP // Map ports with UPnP MapPort(GetBoolArg("-upnp", USE_UPNP)); +#endif // Send and receive from sockets, accept connections - threadGroup->create_thread(boost::bind(&TraceThread, "net", &ThreadSocketHandler)); + threadGroup.create_thread(boost::bind(&TraceThread, "net", &ThreadSocketHandler)); // Initiate outbound connections from -addnode - threadGroup->create_thread(boost::bind(&TraceThread, "addcon", &ThreadOpenAddedConnections)); + threadGroup.create_thread(boost::bind(&TraceThread, "addcon", &ThreadOpenAddedConnections)); // Initiate outbound connections - threadGroup->create_thread(boost::bind(&TraceThread, "opencon", &ThreadOpenConnections)); + threadGroup.create_thread(boost::bind(&TraceThread, "opencon", &ThreadOpenConnections)); // Process messages - threadGroup->create_thread(boost::bind(&TraceThread, "msghand", &ThreadMessageHandler)); + threadGroup.create_thread(boost::bind(&TraceThread, "msghand", &ThreadMessageHandler)); // Dump network addresses - threadGroup->create_thread(boost::bind(&LoopForever, "dumpaddr", &DumpAddresses, 10000)); + threadGroup.create_thread(boost::bind(&LoopForever, "dumpaddr", &DumpAddresses, 10000)); } bool StopNode() @@ -1826,23 +1824,10 @@ bool StopNode() printf("StopNode()\n"); GenerateBitcoins(false, NULL); MapPort(false); - fShutdown = true; nTransactionsUpdated++; - int64 nStart = GetTime(); if (semOutbound) for (int i=0; ipost(); - do - { - int nThreadsRunning = 0; - for (int n = 0; n < THREAD_MAX; n++) - nThreadsRunning += vnThreadsRunning[n]; - if (nThreadsRunning == 0) - break; - if (GetTime() - nStart > 20) - break; - MilliSleep(20); - } while(true); MilliSleep(50); DumpAddresses(); diff --git a/src/net.h b/src/net.h index 1a6f7d4de..65e83f909 100644 --- a/src/net.h +++ b/src/net.h @@ -40,7 +40,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL, int64 nTime void MapPort(bool fUseUPnP); unsigned short GetListenPort(); bool BindListenPort(const CService &bindAddr, std::string& strError=REF(std::string())); -void StartNode(void* parg); +void StartNode(boost::thread_group& threadGroup); bool StopNode(); void SocketSendData(CNode *pnode); @@ -69,16 +69,9 @@ void SetReachable(enum Network net, bool fFlag = true); CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL); -/** Thread types */ -enum threadId -{ - THREAD_MAX -}; - extern bool fDiscover; extern uint64 nLocalServices; extern uint64 nLocalHostNonce; -extern boost::array vnThreadsRunning; extern CAddrMan addrman; extern std::vector vNodes; diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index a805e350e..b61921fca 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -260,9 +260,9 @@ int main(int argc, char *argv[]) guiref = 0; } // Shutdown the core and its threads, but don't exit Bitcoin-Qt here - Shutdown(NULL); threadGroup.interrupt_all(); threadGroup.join_all(); + Shutdown(); } else { diff --git a/src/txdb.cpp b/src/txdb.cpp index ae7aceb7f..5b0527c76 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -115,12 +115,13 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) { pcursor->SeekToFirst(); while (pcursor->Valid()) { + boost::this_thread::interruption_point(); try { leveldb::Slice slKey = pcursor->key(); CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION); char chType; ssKey >> chType; - if (chType == 'c' && !fRequestShutdown) { + if (chType == 'c') { leveldb::Slice slValue = pcursor->value(); CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION); CCoins coins; @@ -178,12 +179,13 @@ bool CBlockTreeDB::LoadBlockIndexGuts() // Load mapBlockIndex while (pcursor->Valid()) { + boost::this_thread::interruption_point(); try { leveldb::Slice slKey = pcursor->key(); CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION); char chType; ssKey >> chType; - if (chType == 'b' && !fRequestShutdown) { + if (chType == 'b') { leveldb::Slice slValue = pcursor->value(); CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION); CDiskBlockIndex diskindex; diff --git a/src/util.cpp b/src/util.cpp index ba012d321..9f5e08a14 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -73,8 +73,6 @@ bool fDebug = false; bool fDebugNet = false; bool fPrintToConsole = false; bool fPrintToDebugger = false; -volatile bool fRequestShutdown = false; -bool fShutdown = false; bool fDaemon = false; bool fServer = false; bool fCommandLine = false; diff --git a/src/util.h b/src/util.h index 0c5ed9163..4d7c81be0 100644 --- a/src/util.h +++ b/src/util.h @@ -134,8 +134,6 @@ extern bool fDebug; extern bool fDebugNet; extern bool fPrintToConsole; extern bool fPrintToDebugger; -extern volatile bool fRequestShutdown; -extern bool fShutdown; extern bool fDaemon; extern bool fServer; extern bool fCommandLine; diff --git a/src/wallet.cpp b/src/wallet.cpp index eecb7d2d2..5761b008f 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1383,7 +1383,6 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet) return nLoadWalletRet; fFirstRunRet = !vchDefaultKey.IsValid(); - NewThread(ThreadFlushWalletDB, &strWalletFile); return DB_LOAD_OK; } diff --git a/src/wallet.h b/src/wallet.h index ecfdafe2e..e750bfd89 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -327,8 +327,7 @@ public: ~CReserveKey() { - if (!fShutdown) - ReturnKey(); + ReturnKey(); } void ReturnKey(); diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 96bc05b11..abaf5a0fd 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -451,8 +451,10 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) } pcursor->close(); } - catch (...) - { + catch (boost::thread_interrupted) { + throw; + } + catch (...) { result = DB_CORRUPT; } @@ -482,12 +484,11 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet) return result; } -void ThreadFlushWalletDB(void* parg) +void ThreadFlushWalletDB(const string& strFile) { // Make this thread recognisable as the wallet flushing thread RenameThread("bitcoin-wallet"); - const string& strFile = ((const string*)parg)[0]; static bool fOneThread; if (fOneThread) return; @@ -498,7 +499,7 @@ void ThreadFlushWalletDB(void* parg) unsigned int nLastSeen = nWalletDBUpdated; unsigned int nLastFlushed = nWalletDBUpdated; int64 nLastWalletUpdate = GetTime(); - while (!fShutdown) + while (true) { MilliSleep(500); @@ -522,8 +523,9 @@ void ThreadFlushWalletDB(void* parg) mi++; } - if (nRefCount == 0 && !fShutdown) + if (nRefCount == 0) { + boost::this_thread::interruption_point(); map::iterator mi = bitdb.mapFileUseCount.find(strFile); if (mi != bitdb.mapFileUseCount.end()) { @@ -548,7 +550,7 @@ bool BackupWallet(const CWallet& wallet, const string& strDest) { if (!wallet.fFileBacked) return false; - while (!fShutdown) + while (true) { { LOCK(bitdb.cs_db);