Browse Source

Shutdown cleanup prep-work

Create a boost::thread_group object at the qt/bitcoind main-loop level
that will hold pointers to all the main-loop threads.

This will replace the vnThreadsRunning[] array.

For testing, ported the BitcoinMiner threads to use its
own boost::thread_group.
0.8
Gavin Andresen 12 years ago
parent
commit
c8c2fbe07f
  1. 21
      src/init.cpp
  2. 3
      src/init.h
  3. 102
      src/main.cpp
  4. 2
      src/net.cpp
  5. 1
      src/net.h
  6. 6
      src/qt/bitcoin.cpp
  7. 9
      src/util.cpp
  8. 3
      src/util.h

21
src/init.cpp

@ -122,6 +122,16 @@ void Shutdown(void* parg)
} }
} }
//
// Signal handlers are very limited in what they are allowed to do, so:
//
void DetectShutdownThread(boost::thread_group* threadGroup)
{
while (fRequestShutdown == false)
Sleep(200);
threadGroup->interrupt_all();
}
void HandleSIGTERM(int) void HandleSIGTERM(int)
{ {
fRequestShutdown = true; fRequestShutdown = true;
@ -143,6 +153,7 @@ void HandleSIGHUP(int)
#if !defined(QT_GUI) #if !defined(QT_GUI)
bool AppInit(int argc, char* argv[]) bool AppInit(int argc, char* argv[])
{ {
boost::thread_group threadGroup;
bool fRet = false; bool fRet = false;
try try
{ {
@ -185,7 +196,7 @@ bool AppInit(int argc, char* argv[])
exit(ret); exit(ret);
} }
fRet = AppInit2(); fRet = AppInit2(threadGroup);
} }
catch (std::exception& e) { catch (std::exception& e) {
PrintExceptionContinue(&e, "AppInit()"); PrintExceptionContinue(&e, "AppInit()");
@ -193,7 +204,11 @@ bool AppInit(int argc, char* argv[])
PrintExceptionContinue(NULL, "AppInit()"); PrintExceptionContinue(NULL, "AppInit()");
} }
if (!fRet) if (!fRet)
{
Shutdown(NULL); Shutdown(NULL);
threadGroup.interrupt_all();
threadGroup.join_all();
}
return fRet; return fRet;
} }
@ -405,7 +420,7 @@ void ThreadImport(void *data) {
/** Initialize bitcoin. /** Initialize bitcoin.
* @pre Parameters should be parsed and config file should be read. * @pre Parameters should be parsed and config file should be read.
*/ */
bool AppInit2() bool AppInit2(boost::thread_group& threadGroup)
{ {
// ********************************************************* Step 1: setup // ********************************************************* Step 1: setup
#ifdef _MSC_VER #ifdef _MSC_VER
@ -449,6 +464,8 @@ bool AppInit2()
sigaction(SIGHUP, &sa_hup, NULL); sigaction(SIGHUP, &sa_hup, NULL);
#endif #endif
threadGroup.create_thread(boost::bind(&DetectShutdownThread, &threadGroup));
// ********************************************************* Step 2: parameter interactions // ********************************************************* Step 2: parameter interactions
fTestNet = GetBoolArg("-testnet"); fTestNet = GetBoolArg("-testnet");

3
src/init.h

@ -7,11 +7,12 @@
#include "wallet.h" #include "wallet.h"
class boost::thread_group;
extern CWallet* pwalletMain; extern CWallet* pwalletMain;
void StartShutdown(); void StartShutdown();
void Shutdown(void* parg); void Shutdown(void* parg);
bool AppInit2(); bool AppInit2(boost::thread_group& threadGroup);
std::string HelpMessage(); std::string HelpMessage();
#endif #endif

102
src/main.cpp

@ -61,8 +61,8 @@ CScript COINBASE_FLAGS;
const string strMessageMagic = "Bitcoin Signed Message:\n"; const string strMessageMagic = "Bitcoin Signed Message:\n";
double dHashesPerSec; double dHashesPerSec = 0.0;
int64 nHPSTimerStart; int64 nHPSTimerStart = 0;
// Settings // Settings
int64 nTransactionFee = 0; int64 nTransactionFee = 0;
@ -4089,6 +4089,8 @@ unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1
nHashesDone = 0xffff+1; nHashesDone = 0xffff+1;
return (unsigned int) -1; return (unsigned int) -1;
} }
if ((nNonce & 0xfff) == 0)
boost::this_thread::interruption_point();
} }
} }
@ -4506,37 +4508,19 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
return true; return true;
} }
void static ThreadBitcoinMiner(void* parg);
static bool fGenerateBitcoins = false;
static bool fLimitProcessors = false;
static int nLimitProcessors = -1;
void static BitcoinMiner(CWallet *pwallet) void static BitcoinMiner(CWallet *pwallet)
{ {
printf("BitcoinMiner started\n"); printf("BitcoinMiner started\n");
SetThreadPriority(THREAD_PRIORITY_LOWEST); SetThreadPriority(THREAD_PRIORITY_LOWEST);
// Make this thread recognisable as the mining thread
RenameThread("bitcoin-miner"); RenameThread("bitcoin-miner");
// Each thread has its own key and counter // Each thread has its own key and counter
CReserveKey reservekey(pwallet); CReserveKey reservekey(pwallet);
unsigned int nExtraNonce = 0; unsigned int nExtraNonce = 0;
while (fGenerateBitcoins) try { loop {
{ while (vNodes.empty())
if (fShutdown)
return;
while (vNodes.empty() || IsInitialBlockDownload())
{
Sleep(1000); Sleep(1000);
if (fShutdown)
return;
if (!fGenerateBitcoins)
return;
}
// //
// Create new block // Create new block
@ -4553,7 +4537,6 @@ void static BitcoinMiner(CWallet *pwallet)
printf("Running BitcoinMiner with %"PRIszu" transactions in block (%u bytes)\n", pblock->vtx.size(), printf("Running BitcoinMiner with %"PRIszu" transactions in block (%u bytes)\n", pblock->vtx.size(),
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION)); ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
// //
// Pre-build hash buffers // Pre-build hash buffers
// //
@ -4626,19 +4609,14 @@ void static BitcoinMiner(CWallet *pwallet)
if (GetTime() - nLogTime > 30 * 60) if (GetTime() - nLogTime > 30 * 60)
{ {
nLogTime = GetTime(); nLogTime = GetTime();
printf("hashmeter %3d CPUs %6.0f khash/s\n", vnThreadsRunning[THREAD_MINER], dHashesPerSec/1000.0); printf("hashmeter %6.0f khash/s\n", dHashesPerSec/1000.0);
} }
} }
} }
} }
// Check for stop or if block needs to be rebuilt // Check for stop or if block needs to be rebuilt
if (fShutdown) boost::this_thread::interruption_point();
return;
if (!fGenerateBitcoins)
return;
if (fLimitProcessors && vnThreadsRunning[THREAD_MINER] > nLimitProcessors)
return;
if (vNodes.empty()) if (vNodes.empty())
break; break;
if (nBlockNonce >= 0xffff0000) if (nBlockNonce >= 0xffff0000)
@ -4658,57 +4636,35 @@ void static BitcoinMiner(CWallet *pwallet)
hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
} }
} }
} } }
} catch (boost::thread_interrupted)
void static ThreadBitcoinMiner(void* parg)
{
CWallet* pwallet = (CWallet*)parg;
try
{ {
vnThreadsRunning[THREAD_MINER]++; printf("BitcoinMiner terminated\n");
BitcoinMiner(pwallet); throw;
vnThreadsRunning[THREAD_MINER]--; }
}
catch (std::exception& e) {
vnThreadsRunning[THREAD_MINER]--;
PrintException(&e, "ThreadBitcoinMiner()");
} catch (...) {
vnThreadsRunning[THREAD_MINER]--;
PrintException(NULL, "ThreadBitcoinMiner()");
}
nHPSTimerStart = 0;
if (vnThreadsRunning[THREAD_MINER] == 0)
dHashesPerSec = 0;
printf("ThreadBitcoinMiner exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINER]);
} }
void GenerateBitcoins(bool fGenerate, CWallet* pwallet) void GenerateBitcoins(bool fGenerate, CWallet* pwallet)
{ {
fGenerateBitcoins = fGenerate; static boost::thread_group* minerThreads = NULL;
nLimitProcessors = GetArg("-genproclimit", -1);
if (nLimitProcessors == 0) int nThreads = GetArg("-genproclimit", -1);
fGenerateBitcoins = false; if (nThreads < 0)
fLimitProcessors = (nLimitProcessors != -1); nThreads = boost::thread::hardware_concurrency();
if (fGenerate) if (minerThreads != NULL)
{ {
int nProcessors = boost::thread::hardware_concurrency(); minerThreads->interrupt_all();
printf("%d processors\n", nProcessors); delete minerThreads;
if (nProcessors < 1) minerThreads = NULL;
nProcessors = 1;
if (fLimitProcessors && nProcessors > nLimitProcessors)
nProcessors = nLimitProcessors;
int nAddThreads = nProcessors - vnThreadsRunning[THREAD_MINER];
printf("Starting %d BitcoinMiner threads\n", nAddThreads);
for (int i = 0; i < nAddThreads; i++)
{
if (!NewThread(ThreadBitcoinMiner, pwallet))
printf("Error: NewThread(ThreadBitcoinMiner) failed\n");
Sleep(10);
}
} }
if (nThreads == 0 || !fGenerate)
return;
minerThreads = new boost::thread_group();
for (int i = 0; i < nThreads; i++)
minerThreads->create_thread(boost::bind(&BitcoinMiner, pwallet));
} }
// Amount compression: // Amount compression:

2
src/net.cpp

@ -2052,6 +2052,7 @@ void StartNode(void* parg)
bool StopNode() bool StopNode()
{ {
printf("StopNode()\n"); printf("StopNode()\n");
GenerateBitcoins(false, NULL);
fShutdown = true; fShutdown = true;
nTransactionsUpdated++; nTransactionsUpdated++;
int64 nStart = GetTime(); int64 nStart = GetTime();
@ -2072,7 +2073,6 @@ bool StopNode()
if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n"); if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n"); if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n"); if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
if (vnThreadsRunning[THREAD_MINER] > 0) printf("ThreadBitcoinMiner still running\n");
if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n"); if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n"); if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
#ifdef USE_UPNP #ifdef USE_UPNP

1
src/net.h

@ -75,7 +75,6 @@ enum threadId
THREAD_SOCKETHANDLER, THREAD_SOCKETHANDLER,
THREAD_OPENCONNECTIONS, THREAD_OPENCONNECTIONS,
THREAD_MESSAGEHANDLER, THREAD_MESSAGEHANDLER,
THREAD_MINER,
THREAD_RPCLISTENER, THREAD_RPCLISTENER,
THREAD_UPNP, THREAD_UPNP,
THREAD_DNSSEED, THREAD_DNSSEED,

6
src/qt/bitcoin.cpp

@ -11,6 +11,7 @@
#include "guiutil.h" #include "guiutil.h"
#include "guiconstants.h" #include "guiconstants.h"
#include "init.h" #include "init.h"
#include "util.h"
#include "ui_interface.h" #include "ui_interface.h"
#include "paymentserver.h" #include "paymentserver.h"
@ -215,9 +216,10 @@ int main(int argc, char *argv[])
if (GUIUtil::GetStartOnSystemStartup()) if (GUIUtil::GetStartOnSystemStartup())
GUIUtil::SetStartOnSystemStartup(true); GUIUtil::SetStartOnSystemStartup(true);
boost::thread_group threadGroup;
BitcoinGUI window; BitcoinGUI window;
guiref = &window; guiref = &window;
if(AppInit2()) if(AppInit2(threadGroup))
{ {
{ {
// Put this in a block, so that the Model objects are cleaned up before // Put this in a block, so that the Model objects are cleaned up before
@ -259,6 +261,8 @@ int main(int argc, char *argv[])
} }
// Shutdown the core and its threads, but don't exit Bitcoin-Qt here // Shutdown the core and its threads, but don't exit Bitcoin-Qt here
Shutdown(NULL); Shutdown(NULL);
threadGroup.interrupt_all();
threadGroup.join_all();
} }
else else
{ {

9
src/util.cpp

@ -1431,9 +1431,12 @@ void RenameThread(const char* name)
// removed. // removed.
pthread_set_name_np(pthread_self(), name); pthread_set_name_np(pthread_self(), name);
// This is XCode 10.6-and-later; bring back if we drop 10.5 support: #elif defined(MAC_OSX) && defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
// #elif defined(MAC_OSX)
// pthread_setname_np(name); // pthread_setname_np is XCode 10.6-and-later
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
pthread_setname_np(name);
#endif
#else #else
// Prevent warnings for unused parameters... // Prevent warnings for unused parameters...

3
src/util.h

@ -15,6 +15,8 @@
typedef int pid_t; /* define for Windows compatibility */ typedef int pid_t; /* define for Windows compatibility */
#endif #endif
#include <map> #include <map>
#include <list>
#include <utility>
#include <vector> #include <vector>
#include <string> #include <string>
@ -523,4 +525,3 @@ inline uint32_t ByteReverse(uint32_t value)
} }
#endif #endif

Loading…
Cancel
Save