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.
This commit is contained in:
parent
87b9931bed
commit
c8c2fbe07f
8 changed files with 63 additions and 82 deletions
21
src/init.cpp
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");
|
||||||
|
|
|
@ -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
|
||||||
|
|
100
src/main.cpp
100
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)
|
|
||||||
fGenerateBitcoins = false;
|
|
||||||
fLimitProcessors = (nLimitProcessors != -1);
|
|
||||||
|
|
||||||
if (fGenerate)
|
int nThreads = GetArg("-genproclimit", -1);
|
||||||
|
if (nThreads < 0)
|
||||||
|
nThreads = boost::thread::hardware_concurrency();
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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...
|
||||||
|
|
|
@ -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…
Add table
Reference in a new issue