aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bitcoinrpc.cpp153
-rw-r--r--src/bitcoinrpc.h3
-rw-r--r--src/checkpoints.cpp16
-rw-r--r--src/checkqueue.h18
-rw-r--r--src/db.cpp10
-rw-r--r--src/db.h2
-rw-r--r--src/init.cpp270
-rw-r--r--src/init.h5
-rw-r--r--src/limitedmap.h100
-rw-r--r--src/main.cpp177
-rw-r--r--src/main.h6
-rw-r--r--src/net.cpp419
-rw-r--r--src/net.h39
-rw-r--r--src/qt/bitcoin.cpp22
-rw-r--r--src/qt/bitcoinamountfield.cpp2
-rw-r--r--src/qt/bitcoingui.cpp26
-rw-r--r--src/qt/bitcoingui.h16
-rw-r--r--src/qt/bitcoinstrings.cpp10
-rw-r--r--src/qt/guiutil.cpp11
-rw-r--r--src/qt/locale/bitcoin_en.ts373
-rw-r--r--src/qt/optionsmodel.cpp5
-rw-r--r--src/qt/res/icons/bitcoin.icnsbin99044 -> 919273 bytes
-rw-r--r--src/qt/res/icons/bitcoin.svg58
-rw-r--r--src/qt/sendcoinsdialog.cpp2
-rw-r--r--src/qt/walletview.cpp136
-rw-r--r--src/qt/walletview.h30
-rw-r--r--src/rpcwallet.cpp2
-rw-r--r--src/test/bignum_tests.cpp24
-rw-r--r--src/test/multisig_tests.cpp4
-rw-r--r--src/test/script_P2SH_tests.cpp4
-rw-r--r--src/test/serialize_tests.cpp4
-rw-r--r--src/test/sigopcount_tests.cpp22
-rw-r--r--src/test/test_bitcoin.cpp6
-rw-r--r--src/test/util_tests.cpp58
-rw-r--r--src/test/wallet_tests.cpp30
-rw-r--r--src/txdb.cpp6
-rw-r--r--src/ui_interface.h3
-rw-r--r--src/util.cpp11
-rw-r--r--src/util.h74
-rw-r--r--src/wallet.cpp1
-rw-r--r--src/wallet.h3
-rw-r--r--src/walletdb.cpp20
42 files changed, 1063 insertions, 1118 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index b6d8de4a18..9c126fc3da 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -30,13 +30,12 @@ using namespace boost;
using namespace boost::asio;
using namespace json_spirit;
-void ThreadRPCServer2(void* parg);
-
static std::string strRPCUserColonPass;
-const Object emptyobj;
-
-void ThreadRPCServer3(void* parg);
+// These are created by StartRPCThreads, destroyed in StopRPCThreads
+static asio::io_service* rpc_io_service = NULL;
+static ssl::context* rpc_ssl_context = NULL;
+static boost::thread_group* rpc_worker_group = NULL;
static inline unsigned short GetDefaultRPCPort()
{
@@ -650,26 +649,7 @@ private:
iostreams::stream< SSLIOStreamDevice<Protocol> > _stream;
};
-void ThreadRPCServer(void* parg)
-{
- // Make this thread recognisable as the RPC listener
- RenameThread("bitcoin-rpclist");
-
- try
- {
- vnThreadsRunning[THREAD_RPCLISTENER]++;
- ThreadRPCServer2(parg);
- vnThreadsRunning[THREAD_RPCLISTENER]--;
- }
- catch (std::exception& e) {
- vnThreadsRunning[THREAD_RPCLISTENER]--;
- PrintException(&e, "ThreadRPCServer()");
- } catch (...) {
- vnThreadsRunning[THREAD_RPCLISTENER]--;
- PrintException(NULL, "ThreadRPCServer()");
- }
- printf("ThreadRPCServer exited\n");
-}
+void ServiceConnection(AcceptedConnection *conn);
// Forward declaration required for RPCListen
template <typename Protocol, typename SocketAcceptorService>
@@ -711,11 +691,8 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol,
AcceptedConnection* conn,
const boost::system::error_code& error)
{
- vnThreadsRunning[THREAD_RPCLISTENER]++;
-
// Immediately start accepting new connections, except when we're cancelled or our socket is closed.
- if (error != asio::error::operation_aborted
- && acceptor->is_open())
+ if (error != asio::error::operation_aborted && acceptor->is_open())
RPCListen(acceptor, context, fUseSSL);
AcceptedConnectionImpl<ip::tcp>* tcp_conn = dynamic_cast< AcceptedConnectionImpl<ip::tcp>* >(conn);
@@ -729,28 +706,22 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol,
// Restrict callers by IP. It is important to
// do this before starting client thread, to filter out
// certain DoS and misbehaving clients.
- else if (tcp_conn
- && !ClientAllowed(tcp_conn->peer.address()))
+ else if (tcp_conn && !ClientAllowed(tcp_conn->peer.address()))
{
// Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
if (!fUseSSL)
conn->stream() << HTTPReply(HTTP_FORBIDDEN, "", false) << std::flush;
delete conn;
}
-
- // start HTTP client thread
- else if (!NewThread(ThreadRPCServer3, conn)) {
- printf("Failed to create RPC server client thread\n");
+ else {
+ ServiceConnection(conn);
+ conn->close();
delete conn;
}
-
- vnThreadsRunning[THREAD_RPCLISTENER]--;
}
-void ThreadRPCServer2(void* parg)
+void StartRPCThreads()
{
- printf("ThreadRPCServer started\n");
-
strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
if ((mapArgs["-rpcpassword"] == "") ||
(mapArgs["-rpcuser"] == mapArgs["-rpcpassword"]))
@@ -763,7 +734,8 @@ void ThreadRPCServer2(void* parg)
else if (mapArgs.count("-daemon"))
strWhatAmI = strprintf(_("To use the %s option"), "\"-daemon\"");
uiInterface.ThreadSafeMessageBox(strprintf(
- _("%s, you must set a rpcpassword in the configuration file:\n %s\n"
+ _("%s, you must set a rpcpassword in the configuration file:\n"
+ "%s\n"
"It is recommended you use the following random password:\n"
"rpcuser=bitcoinrpc\n"
"rpcpassword=%s\n"
@@ -780,27 +752,28 @@ void ThreadRPCServer2(void* parg)
return;
}
- const bool fUseSSL = GetBoolArg("-rpcssl");
+ assert(rpc_io_service == NULL);
+ rpc_io_service = new asio::io_service();
+ rpc_ssl_context = new ssl::context(*rpc_io_service, ssl::context::sslv23);
- asio::io_service io_service;
+ const bool fUseSSL = GetBoolArg("-rpcssl");
- ssl::context context(io_service, ssl::context::sslv23);
if (fUseSSL)
{
- context.set_options(ssl::context::no_sslv2);
+ rpc_ssl_context->set_options(ssl::context::no_sslv2);
filesystem::path pathCertFile(GetArg("-rpcsslcertificatechainfile", "server.cert"));
if (!pathCertFile.is_complete()) pathCertFile = filesystem::path(GetDataDir()) / pathCertFile;
- if (filesystem::exists(pathCertFile)) context.use_certificate_chain_file(pathCertFile.string());
+ if (filesystem::exists(pathCertFile)) rpc_ssl_context->use_certificate_chain_file(pathCertFile.string());
else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", pathCertFile.string().c_str());
filesystem::path pathPKFile(GetArg("-rpcsslprivatekeyfile", "server.pem"));
if (!pathPKFile.is_complete()) pathPKFile = filesystem::path(GetDataDir()) / pathPKFile;
- if (filesystem::exists(pathPKFile)) context.use_private_key_file(pathPKFile.string(), ssl::context::pem);
+ if (filesystem::exists(pathPKFile)) rpc_ssl_context->use_private_key_file(pathPKFile.string(), ssl::context::pem);
else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pathPKFile.string().c_str());
string strCiphers = GetArg("-rpcsslciphers", "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
- SSL_CTX_set_cipher_list(context.impl(), strCiphers.c_str());
+ SSL_CTX_set_cipher_list(rpc_ssl_context->impl(), strCiphers.c_str());
}
// Try a dual IPv6/IPv4 socket, falling back to separate IPv4 and IPv6 sockets
@@ -808,9 +781,7 @@ void ThreadRPCServer2(void* parg)
asio::ip::address bindAddress = loopback ? asio::ip::address_v6::loopback() : asio::ip::address_v6::any();
ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", GetDefaultRPCPort()));
boost::system::error_code v6_only_error;
- boost::shared_ptr<ip::tcp::acceptor> acceptor(new ip::tcp::acceptor(io_service));
-
- boost::signals2::signal<void ()> StopRequests;
+ boost::shared_ptr<ip::tcp::acceptor> acceptor(new ip::tcp::acceptor(*rpc_io_service));
bool fListening = false;
std::string strerr;
@@ -825,11 +796,7 @@ void ThreadRPCServer2(void* parg)
acceptor->bind(endpoint);
acceptor->listen(socket_base::max_connections);
- RPCListen(acceptor, context, fUseSSL);
- // Cancel outstanding listen-requests for this acceptor when shutting down
- StopRequests.connect(signals2::slot<void ()>(
- static_cast<void (ip::tcp::acceptor::*)()>(&ip::tcp::acceptor::close), acceptor.get())
- .track(acceptor));
+ RPCListen(acceptor, *rpc_ssl_context, fUseSSL);
fListening = true;
}
@@ -845,17 +812,13 @@ void ThreadRPCServer2(void* parg)
bindAddress = loopback ? asio::ip::address_v4::loopback() : asio::ip::address_v4::any();
endpoint.address(bindAddress);
- acceptor.reset(new ip::tcp::acceptor(io_service));
+ acceptor.reset(new ip::tcp::acceptor(*rpc_io_service));
acceptor->open(endpoint.protocol());
acceptor->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
acceptor->bind(endpoint);
acceptor->listen(socket_base::max_connections);
- RPCListen(acceptor, context, fUseSSL);
- // Cancel outstanding listen-requests for this acceptor when shutting down
- StopRequests.connect(signals2::slot<void ()>(
- static_cast<void (ip::tcp::acceptor::*)()>(&ip::tcp::acceptor::close), acceptor.get())
- .track(acceptor));
+ RPCListen(acceptor, *rpc_ssl_context, fUseSSL);
fListening = true;
}
@@ -871,11 +834,20 @@ void ThreadRPCServer2(void* parg)
return;
}
- vnThreadsRunning[THREAD_RPCLISTENER]--;
- while (!fShutdown)
- io_service.run_one();
- vnThreadsRunning[THREAD_RPCLISTENER]++;
- StopRequests();
+ rpc_worker_group = new boost::thread_group();
+ for (int i = 0; i < GetArg("-rpcthreads", 4); i++)
+ rpc_worker_group->create_thread(boost::bind(&asio::io_service::run, rpc_io_service));
+}
+
+void StopRPCThreads()
+{
+ if (rpc_io_service == NULL) return;
+
+ rpc_io_service->stop();
+ rpc_worker_group->join_all();
+ delete rpc_worker_group; rpc_worker_group = NULL;
+ delete rpc_ssl_context; rpc_ssl_context = NULL;
+ delete rpc_io_service; rpc_io_service = NULL;
}
class JSONRequest
@@ -952,32 +924,11 @@ static string JSONRPCExecBatch(const Array& vReq)
return write_string(Value(ret), false) + "\n";
}
-static CCriticalSection cs_THREAD_RPCHANDLER;
-
-void ThreadRPCServer3(void* parg)
+void ServiceConnection(AcceptedConnection *conn)
{
- // Make this thread recognisable as the RPC handler
- RenameThread("bitcoin-rpchand");
-
- {
- LOCK(cs_THREAD_RPCHANDLER);
- vnThreadsRunning[THREAD_RPCHANDLER]++;
- }
- AcceptedConnection *conn = (AcceptedConnection *) parg;
-
bool fRun = true;
- loop {
- if (fShutdown || !fRun)
- {
- conn->close();
- delete conn;
- {
- LOCK(cs_THREAD_RPCHANDLER);
- --vnThreadsRunning[THREAD_RPCHANDLER];
- }
- return;
- }
-
+ while (fRun)
+ {
int nProto = 0;
map<string, string> mapHeaders;
string strRequest, strMethod, strURI;
@@ -1002,7 +953,7 @@ void ThreadRPCServer3(void* parg)
If this results in a DOS the user really
shouldn't have their RPC port exposed.*/
if (mapArgs["-rpcpassword"].size() < 20)
- Sleep(250);
+ MilliSleep(250);
conn->stream() << HTTPReply(HTTP_UNAUTHORIZED, "", false) << std::flush;
break;
@@ -1048,12 +999,6 @@ void ThreadRPCServer3(void* parg)
break;
}
}
-
- delete conn;
- {
- LOCK(cs_THREAD_RPCHANDLER);
- vnThreadsRunning[THREAD_RPCHANDLER]--;
- }
}
json_spirit::Value CRPCTable::execute(const std::string &strMethod, const json_spirit::Array &params) const
@@ -1276,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()");
}
@@ -1320,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/bitcoinrpc.h b/src/bitcoinrpc.h
index 6a3554aea6..315fd92383 100644
--- a/src/bitcoinrpc.h
+++ b/src/bitcoinrpc.h
@@ -67,7 +67,8 @@ enum RPCErrorCode
json_spirit::Object JSONRPCError(int code, const std::string& message);
-void ThreadRPCServer(void* parg);
+void StartRPCThreads();
+void StopRPCThreads();
int CommandLineRPC(int argc, char *argv[]);
/** Convert parameter values for RPC call from strings to command-specific JSON objects. */
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
index 62234b9117..9e8e0f7024 100644
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -15,11 +15,11 @@ namespace Checkpoints
typedef std::map<int, uint256> MapCheckpoints;
// How many times we expect transactions after the last checkpoint to
- // be slower. This number is conservative. On multi-core CPUs with
- // parallel signature checking enabled, this number is way too high.
- // We prefer a progressbar that's faster at the end than the other
- // way around, though.
- static const double fSigcheckVerificationFactor = 15.0;
+ // be slower. This number is a compromise, as it can't be accurate for
+ // every system. When reindexing from a fast disk with a slow CPU, it
+ // can be up to 20, while when downloading from a slow network with a
+ // fast multicore CPU, it won't be much higher than 1.
+ static const double fSigcheckVerificationFactor = 5.0;
struct CCheckpointData {
const MapCheckpoints *mapCheckpoints;
@@ -48,10 +48,10 @@ namespace Checkpoints
;
static const CCheckpointData data = {
&mapCheckpoints,
- 1357902690, // * UNIX timestamp of last checkpoint block
- 11011160, // * total number of transactions between genesis and last checkpoint
+ 1363044259, // * UNIX timestamp of last checkpoint block
+ 14264869, // * total number of transactions between genesis and last checkpoint
// (the tx=... number in the SetBestChain debug.log lines)
- 50000.0 // * estimated number of transactions per day after checkpoint
+ 60000.0 // * estimated number of transactions per day after checkpoint
};
static MapCheckpoints mapCheckpointsTestnet =
diff --git a/src/checkqueue.h b/src/checkqueue.h
index 12dde36fe7..eba424fbaa 100644
--- a/src/checkqueue.h
+++ b/src/checkqueue.h
@@ -33,9 +33,6 @@ private:
// Master thread blocks on this when out of work
boost::condition_variable condMaster;
- // Quit method blocks on this until all workers are gone
- boost::condition_variable condQuit;
-
// The queue of elements to be processed.
// As the order of booleans doesn't matter, it is used as a LIFO (stack)
std::vector<T> queue;
@@ -85,8 +82,6 @@ private:
while (queue.empty()) {
if ((fMaster || fQuit) && nTodo == 0) {
nTotal--;
- if (nTotal==0)
- condQuit.notify_one();
bool fRet = fAllOk;
// reset the status for new work later
if (fMaster)
@@ -151,20 +146,7 @@ public:
condWorker.notify_all();
}
- // Shut the queue down
- void Quit() {
- boost::unique_lock<boost::mutex> lock(mutex);
- fQuit = true;
- // No need to wake the master, as he will quit automatically when all jobs are
- // done.
- condWorker.notify_all();
-
- while (nTotal > 0)
- condQuit.wait(lock);
- }
-
~CCheckQueue() {
- Quit();
}
friend class CCheckQueueControl<T>;
diff --git a/src/db.cpp b/src/db.cpp
index e51d5d2cba..35d6cca890 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);
@@ -413,7 +411,7 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
return fSuccess;
}
}
- Sleep(100);
+ MilliSleep(100);
}
return false;
}
diff --git a/src/db.h b/src/db.h
index 9c01060a1c..206da91e9e 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 bb22b1d246..ee69d2207f 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -40,85 +40,82 @@ enum BindFlags {
// Shutdown
//
-void ExitTimeout(void* parg)
-{
-#ifdef WIN32
- Sleep(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, 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;
+}
+bool ShutdownRequested()
+{
+ return fRequestShutdown;
}
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");
-
- bool fFirstThread = false;
+ nTransactionsUpdated++;
+ StopRPCThreads();
+ bitdb.Flush(false);
+ StopNode();
{
- TRY_LOCK(cs_Shutdown, lockShutdown);
- if (lockShutdown)
- {
- fFirstThread = !fTaken;
- fTaken = true;
- }
+ LOCK(cs_main);
+ if (pblocktree)
+ pblocktree->Flush();
+ if (pcoinsTip)
+ pcoinsTip->Flush();
+ delete pcoinsTip; pcoinsTip = NULL;
+ delete pcoinsdbview; pcoinsdbview = NULL;
+ delete pblocktree; pblocktree = NULL;
}
- static bool fExit;
- if (fFirstThread)
- {
- fShutdown = true;
- fRequestShutdown = true;
- nTransactionsUpdated++;
- bitdb.Flush(false);
- {
- LOCK(cs_main);
- ThreadScriptCheckQuit();
- }
- 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);
- Sleep(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
+ bitdb.Flush(true);
+ boost::filesystem::remove(GetPidFile());
+ UnregisterWallet(pwalletMain);
+ delete pwalletMain;
+}
+
+//
+// Signal handlers are very limited in what they are allowed to do, so:
+//
+void DetectShutdownThread(boost::thread_group* threadGroup)
+{
+ // Tell the main threads to shutdown.
+ while (!fRequestShutdown)
{
- while (!fExit)
- Sleep(500);
- Sleep(100);
- ExitThread(0);
+ MilliSleep(200);
+ if (fRequestShutdown)
+ threadGroup->interrupt_all();
}
}
@@ -143,6 +140,9 @@ void HandleSIGHUP(int)
#if !defined(QT_GUI)
bool AppInit(int argc, char* argv[])
{
+ boost::thread_group threadGroup;
+ boost::thread* detectShutdownThread = NULL;
+
bool fRet = false;
try
{
@@ -154,7 +154,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,16 +184,52 @@ 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
- fRet = AppInit2();
+ detectShutdownThread = new boost::thread(boost::bind(&DetectShutdownThread, &threadGroup));
+ fRet = AppInit2(threadGroup);
}
catch (std::exception& e) {
PrintExceptionContinue(&e, "AppInit()");
} catch (...) {
PrintExceptionContinue(NULL, "AppInit()");
}
- if (!fRet)
- Shutdown(NULL);
+ if (!fRet) {
+ if (detectShutdownThread)
+ detectShutdownThread->interrupt();
+ threadGroup.interrupt_all();
+ }
+
+ if (detectShutdownThread)
+ {
+ detectShutdownThread->join();
+ delete detectShutdownThread;
+ detectShutdownThread = NULL;
+ }
+ Shutdown();
+
return fRet;
}
@@ -210,7 +246,7 @@ int main(int argc, char* argv[])
if (fRet && fDaemon)
return 0;
- return 1;
+ return (fRet ? 0 : 1);
}
#endif
@@ -298,6 +334,7 @@ std::string HelpMessage()
" -rpcport=<port> " + _("Listen for JSON-RPC connections on <port> (default: 8332 or testnet: 18332)") + "\n" +
" -rpcallowip=<ip> " + _("Allow JSON-RPC connections from specified IP address") + "\n" +
" -rpcconnect=<ip> " + _("Send commands to node running on <ip> (default: 127.0.0.1)") + "\n" +
+ " -rpcthreads=<n> " + _("Use this many threads to service RPC calls (default: 4)") + "\n" +
" -blocknotify=<cmd> " + _("Execute command when the best block changes (%s in cmd is replaced by block hash)") + "\n" +
" -walletnotify=<cmd> " + _("Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)") + "\n" +
" -alertnotify=<cmd> " + _("Execute command when a relevant alert is received (%s in cmd is replaced by message)") + "\n" +
@@ -339,22 +376,16 @@ struct CImportingNow
}
};
-struct CImportData {
- std::vector<boost::filesystem::path> vFiles;
-};
-
-void ThreadImport(void *data) {
- CImportData *import = reinterpret_cast<CImportData*>(data);
+void ThreadImport(std::vector<boost::filesystem::path> vImportFiles)
+{
RenameThread("bitcoin-loadblk");
- vnThreadsRunning[THREAD_IMPORT]++;
-
// -reindex
if (fReindex) {
CImportingNow imp;
int nFile = 0;
- while (!fRequestShutdown) {
+ while (true) {
CDiskBlockPos pos(nFile, 0);
FILE *file = OpenBlockFile(pos, true);
if (!file)
@@ -363,18 +394,16 @@ void ThreadImport(void *data) {
LoadExternalBlockFile(file, &pos);
nFile++;
}
- if (!fRequestShutdown) {
- pblocktree->WriteReindexing(false);
- fReindex = false;
- printf("Reindexing finished\n");
- // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked):
- InitBlockIndex();
- }
+ pblocktree->WriteReindexing(false);
+ fReindex = false;
+ printf("Reindexing finished\n");
+ // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked):
+ InitBlockIndex();
}
// hardcoded $DATADIR/bootstrap.dat
filesystem::path pathBootstrap = GetDataDir() / "bootstrap.dat";
- if (filesystem::exists(pathBootstrap) && !fRequestShutdown) {
+ if (filesystem::exists(pathBootstrap)) {
FILE *file = fopen(pathBootstrap.string().c_str(), "rb");
if (file) {
CImportingNow imp;
@@ -386,9 +415,7 @@ void ThreadImport(void *data) {
}
// -loadblock=
- BOOST_FOREACH(boost::filesystem::path &path, import->vFiles) {
- if (fRequestShutdown)
- break;
+ BOOST_FOREACH(boost::filesystem::path &path, vImportFiles) {
FILE *file = fopen(path.string().c_str(), "rb");
if (file) {
CImportingNow imp;
@@ -396,16 +423,12 @@ void ThreadImport(void *data) {
LoadExternalBlockFile(file);
}
}
-
- delete import;
-
- vnThreadsRunning[THREAD_IMPORT]--;
}
/** Initialize bitcoin.
* @pre Parameters should be parsed and config file should be read.
*/
-bool AppInit2()
+bool AppInit2(boost::thread_group& threadGroup)
{
// ********************************************************* Step 1: setup
#ifdef _MSC_VER
@@ -506,12 +529,6 @@ bool AppInit2()
else
fDebugNet = GetBoolArg("-debugnet");
-#if !defined(WIN32) && !defined(QT_GUI)
- fDaemon = GetBoolArg("-daemon");
-#else
- fDaemon = false;
-#endif
-
if (fDaemon)
fServer = true;
else
@@ -559,28 +576,6 @@ bool AppInit2()
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");
@@ -598,7 +593,7 @@ bool AppInit2()
if (nScriptCheckThreads) {
printf("Using %u threads for script verification\n", nScriptCheckThreads);
for (int i=0; i<nScriptCheckThreads-1; i++)
- NewThread(ThreadScriptCheck, NULL);
+ threadGroup.create_thread(&ThreadScriptCheck);
}
int64 nStart;
@@ -699,9 +694,6 @@ bool AppInit2()
fNoListen = !GetBoolArg("-listen", true);
fDiscover = GetBoolArg("-discover", true);
fNameLookup = GetBoolArg("-dns", true);
-#ifdef USE_UPNP
- fUseUPnP = GetBoolArg("-upnp", USE_UPNP);
-#endif
bool fBound = false;
if (!fNoListen) {
@@ -984,13 +976,13 @@ bool AppInit2()
if (!ConnectBestBlock(state))
strErrors << "Failed to connect best block";
- CImportData *pimport = new CImportData();
+ std::vector<boost::filesystem::path> vImportFiles;
if (mapArgs.count("-loadblock"))
{
BOOST_FOREACH(string strFile, mapMultiArgs["-loadblock"])
- pimport->vFiles.push_back(strFile);
+ vImportFiles.push_back(strFile);
}
- NewThread(ThreadImport, pimport);
+ threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles));
// ********************************************************* Step 10: load peers
@@ -1021,11 +1013,13 @@ bool AppInit2()
printf("mapWallet.size() = %"PRIszu"\n", pwalletMain->mapWallet.size());
printf("mapAddressBook.size() = %"PRIszu"\n", pwalletMain->mapAddressBook.size());
- if (!NewThread(StartNode, NULL))
- InitError(_("Error: could not start node"));
+ StartNode(threadGroup);
if (fServer)
- NewThread(ThreadRPCServer, NULL);
+ StartRPCThreads();
+
+ // Generate coins in the background
+ GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain);
// ********************************************************* Step 12: finished
@@ -1037,12 +1031,8 @@ bool AppInit2()
// 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)
- Sleep(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 8308ee648b..5927670c83 100644
--- a/src/init.h
+++ b/src/init.h
@@ -10,8 +10,9 @@
extern CWallet* pwalletMain;
void StartShutdown();
-void Shutdown(void* parg);
-bool AppInit2();
+bool ShutdownRequested();
+void Shutdown();
+bool AppInit2(boost::thread_group& threadGroup);
std::string HelpMessage();
#endif
diff --git a/src/limitedmap.h b/src/limitedmap.h
new file mode 100644
index 0000000000..7049d68e5a
--- /dev/null
+++ b/src/limitedmap.h
@@ -0,0 +1,100 @@
+// Copyright (c) 2012 The Bitcoin developers
+// Distributed under the MIT/X11 software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_LIMITEDMAP_H
+#define BITCOIN_LIMITEDMAP_H
+
+#include <map>
+#include <deque>
+
+/** STL-like map container that only keeps the N elements with the highest value. */
+template <typename K, typename V> class limitedmap
+{
+public:
+ typedef K key_type;
+ typedef V mapped_type;
+ typedef std::pair<const key_type, mapped_type> value_type;
+ typedef typename std::map<K, V>::const_iterator const_iterator;
+ typedef typename std::map<K, V>::size_type size_type;
+
+protected:
+ std::map<K, V> map;
+ typedef typename std::map<K, V>::iterator iterator;
+ std::multimap<V, iterator> rmap;
+ typedef typename std::multimap<V, iterator>::iterator rmap_iterator;
+ size_type nMaxSize;
+
+public:
+ limitedmap(size_type nMaxSizeIn = 0) { nMaxSize = nMaxSizeIn; }
+ const_iterator begin() const { return map.begin(); }
+ const_iterator end() const { return map.end(); }
+ size_type size() const { return map.size(); }
+ bool empty() const { return map.empty(); }
+ const_iterator find(const key_type& k) const { return map.find(k); }
+ size_type count(const key_type& k) const { return map.count(k); }
+ void insert(const value_type& x)
+ {
+ std::pair<iterator, bool> ret = map.insert(x);
+ if (ret.second)
+ {
+ if (nMaxSize && map.size() == nMaxSize)
+ {
+ map.erase(rmap.begin()->second);
+ rmap.erase(rmap.begin());
+ }
+ rmap.insert(make_pair(x.second, ret.first));
+ }
+ return;
+ }
+ void erase(const key_type& k)
+ {
+ iterator itTarget = map.find(k);
+ if (itTarget == map.end())
+ return;
+ std::pair<rmap_iterator, rmap_iterator> itPair = rmap.equal_range(itTarget->second);
+ for (rmap_iterator it = itPair.first; it != itPair.second; ++it)
+ if (it->second == itTarget)
+ {
+ rmap.erase(it);
+ map.erase(itTarget);
+ return;
+ }
+ // Shouldn't ever get here
+ assert(0); //TODO remove me
+ map.erase(itTarget);
+ }
+ void update(const_iterator itIn, const mapped_type& v)
+ {
+ //TODO: When we switch to C++11, use map.erase(itIn, itIn) to get the non-const iterator
+ iterator itTarget = map.find(itIn->first);
+ if (itTarget == map.end())
+ return;
+ std::pair<rmap_iterator, rmap_iterator> itPair = rmap.equal_range(itTarget->second);
+ for (rmap_iterator it = itPair.first; it != itPair.second; ++it)
+ if (it->second == itTarget)
+ {
+ rmap.erase(it);
+ itTarget->second = v;
+ rmap.insert(make_pair(v, itTarget));
+ return;
+ }
+ // Shouldn't ever get here
+ assert(0); //TODO remove me
+ itTarget->second = v;
+ rmap.insert(make_pair(v, itTarget));
+ }
+ size_type max_size() const { return nMaxSize; }
+ size_type max_size(size_type s)
+ {
+ if (s)
+ while (map.size() > s)
+ {
+ map.erase(rmap.begin()->second);
+ rmap.erase(rmap.begin());
+ }
+ nMaxSize = s;
+ return nMaxSize;
+ }
+};
+
+#endif
diff --git a/src/main.cpp b/src/main.cpp
index b29091b4fe..fb8f1b3b1f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -61,8 +61,8 @@ CScript COINBASE_FLAGS;
const string strMessageMagic = "Bitcoin Signed Message:\n";
-double dHashesPerSec;
-int64 nHPSTimerStart;
+double dHashesPerSec = 0.0;
+int64 nHPSTimerStart = 0;
// Settings
int64 nTransactionFee = 0;
@@ -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;
@@ -1560,15 +1559,9 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
static CCheckQueue<CScriptCheck> scriptcheckqueue(128);
-void ThreadScriptCheck(void*) {
- vnThreadsRunning[THREAD_SCRIPTCHECK]++;
+void ThreadScriptCheck() {
RenameThread("bitcoin-scriptch");
scriptcheckqueue.Thread();
- vnThreadsRunning[THREAD_SCRIPTCHECK]--;
-}
-
-void ThreadScriptCheckQuit() {
- scriptcheckqueue.Quit();
}
bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsViewCache &view, bool fJustCheck)
@@ -1868,9 +1861,10 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
bnBestChainWork = pindexNew->bnChainWork;
nTimeBestReceived = GetTime();
nTransactionsUpdated++;
- printf("SetBestChain: new best=%s height=%d work=%s tx=%lu date=%s\n",
+ printf("SetBestChain: new best=%s height=%d work=%s tx=%lu date=%s progress=%f\n",
BlockHashStr(hashBestChain).c_str(), nBestHeight, bnBestChainWork.ToString().c_str(), (unsigned long)pindexNew->nChainTx,
- DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexBest->GetBlockTime()).c_str());
+ DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexBest->GetBlockTime()).c_str(),
+ Checkpoints::GuessVerificationProgress(pindexBest));
// Check the version of the last 100 blocks to see if we need to upgrade:
if (!fIsInitialDownload)
@@ -2463,7 +2457,6 @@ uint256 CPartialMerkleTree::ExtractMatches(std::vector<uint256> &vMatch) {
bool AbortNode(const std::string &strMessage) {
- fRequestShutdown = true;
strMiscWarning = strMessage;
printf("*** %s\n", strMessage.c_str());
uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_ERROR);
@@ -2542,8 +2535,7 @@ bool static LoadBlockIndexDB()
if (!pblocktree->LoadBlockIndexGuts())
return false;
- if (fRequestShutdown)
- return true;
+ boost::this_thread::interruption_point();
// Calculate bnChainWork
vector<pair<int, CBlockIndex*> > vSortedByHeight;
@@ -2623,7 +2615,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
@@ -2660,7 +2653,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))
@@ -2867,7 +2861,9 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
}
}
uint64 nRewind = blkdat.GetPos();
- while (blkdat.good() && !blkdat.eof() && !fRequestShutdown) {
+ while (blkdat.good() && !blkdat.eof()) {
+ boost::this_thread::interruption_point();
+
blkdat.SetPos(nRewind);
nRewind++; // start one byte further next time, in case of failure
blkdat.SetLimit(); // remove former limit
@@ -3042,8 +3038,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)
@@ -3301,8 +3296,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);
@@ -3370,8 +3365,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);
@@ -3803,8 +3797,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)
{
@@ -3823,6 +3816,9 @@ bool ProcessMessages(CNode* pfrom)
PrintExceptionContinue(&e, "ProcessMessages()");
}
}
+ catch (boost::thread_interrupted) {
+ throw;
+ }
catch (std::exception& e) {
PrintExceptionContinue(&e, "ProcessMessages()");
} catch (...) {
@@ -3994,7 +3990,6 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
pto->PushMessage("getdata", vGetData);
vGetData.clear();
}
- mapAlreadyAskedFor[inv] = nNow;
}
pto->mapAskFor.erase(pto->mapAskFor.begin());
}
@@ -4089,6 +4084,8 @@ unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1
nHashesDone = 0xffff+1;
return (unsigned int) -1;
}
+ if ((nNonce & 0xfff) == 0)
+ boost::this_thread::interruption_point();
}
}
@@ -4506,37 +4503,19 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
return true;
}
-void static ThreadBitcoinMiner(void* parg);
-
-static bool fGenerateBitcoins = false;
-static bool fLimitProcessors = false;
-static int nLimitProcessors = -1;
-
void static BitcoinMiner(CWallet *pwallet)
{
printf("BitcoinMiner started\n");
SetThreadPriority(THREAD_PRIORITY_LOWEST);
-
- // Make this thread recognisable as the mining thread
RenameThread("bitcoin-miner");
// Each thread has its own key and counter
CReserveKey reservekey(pwallet);
unsigned int nExtraNonce = 0;
- while (fGenerateBitcoins)
- {
- if (fShutdown)
- return;
- while (vNodes.empty() || IsInitialBlockDownload())
- {
- Sleep(1000);
- if (fShutdown)
- return;
- if (!fGenerateBitcoins)
- return;
- }
-
+ try { loop {
+ while (vNodes.empty())
+ MilliSleep(1000);
//
// Create new block
@@ -4553,7 +4532,6 @@ void static BitcoinMiner(CWallet *pwallet)
printf("Running BitcoinMiner with %"PRIszu" transactions in block (%u bytes)\n", pblock->vtx.size(),
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
-
//
// Pre-build hash buffers
//
@@ -4626,19 +4604,14 @@ void static BitcoinMiner(CWallet *pwallet)
if (GetTime() - nLogTime > 30 * 60)
{
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
- if (fShutdown)
- return;
- if (!fGenerateBitcoins)
- return;
- if (fLimitProcessors && vnThreadsRunning[THREAD_MINER] > nLimitProcessors)
- return;
+ boost::this_thread::interruption_point();
if (vNodes.empty())
break;
if (nBlockNonce >= 0xffff0000)
@@ -4658,57 +4631,35 @@ void static BitcoinMiner(CWallet *pwallet)
hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
}
}
- }
-}
-
-void static ThreadBitcoinMiner(void* parg)
-{
- CWallet* pwallet = (CWallet*)parg;
- try
+ } }
+ catch (boost::thread_interrupted)
{
- vnThreadsRunning[THREAD_MINER]++;
- BitcoinMiner(pwallet);
- 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]);
+ printf("BitcoinMiner terminated\n");
+ throw;
+ }
}
-
void GenerateBitcoins(bool fGenerate, CWallet* pwallet)
{
- fGenerateBitcoins = fGenerate;
- nLimitProcessors = GetArg("-genproclimit", -1);
- if (nLimitProcessors == 0)
- fGenerateBitcoins = false;
- fLimitProcessors = (nLimitProcessors != -1);
+ static boost::thread_group* minerThreads = NULL;
+
+ int nThreads = GetArg("-genproclimit", -1);
+ if (nThreads < 0)
+ nThreads = boost::thread::hardware_concurrency();
- if (fGenerate)
+ if (minerThreads != NULL)
{
- int nProcessors = boost::thread::hardware_concurrency();
- printf("%d processors\n", nProcessors);
- if (nProcessors < 1)
- 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);
- }
+ minerThreads->interrupt_all();
+ delete minerThreads;
+ minerThreads = NULL;
}
+
+ 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:
@@ -4764,3 +4715,29 @@ uint64 CTxOutCompressor::DecompressAmount(uint64 x)
}
return n;
}
+
+
+class CMainCleanup
+{
+public:
+ CMainCleanup() {}
+ ~CMainCleanup() {
+ // block headers
+ std::map<uint256, CBlockIndex*>::iterator it1 = mapBlockIndex.begin();
+ for (; it1 != mapBlockIndex.end(); it1++)
+ delete (*it1).second;
+ mapBlockIndex.clear();
+
+ // orphan blocks
+ std::map<uint256, CBlock*>::iterator it2 = mapOrphanBlocks.begin();
+ for (; it2 != mapOrphanBlocks.end(); it2++)
+ delete (*it2).second;
+ mapOrphanBlocks.clear();
+
+ // orphan transactions
+ std::map<uint256, CDataStream*>::iterator it3 = mapOrphanTransactions.begin();
+ for (; it3 != mapOrphanTransactions.end(); it3++)
+ delete (*it3).second;
+ mapOrphanTransactions.clear();
+ }
+} instance_of_cmaincleanup;
diff --git a/src/main.h b/src/main.h
index 43c3051e4c..c6bd77d3dc 100644
--- a/src/main.h
+++ b/src/main.h
@@ -150,12 +150,8 @@ CBlockIndex* FindBlockByHeight(int nHeight);
bool ProcessMessages(CNode* pfrom);
/** Send queued protocol messages to be sent to a give node */
bool SendMessages(CNode* pto, bool fSendTrickle);
-/** Run the importer thread, which deals with reindexing, loading bootstrap.dat, and whatever is passed to -loadblock */
-void ThreadImport(void *parg);
/** Run an instance of the script checking thread */
-void ThreadScriptCheck(void* parg);
-/** Stop the script checking threads */
-void ThreadScriptCheckQuit();
+void ThreadScriptCheck();
/** Run the miner threads */
void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
/** Generate a new block, without valid proof-of-work */
diff --git a/src/net.cpp b/src/net.cpp
index 9ee6cb423c..5f8b5ba32b 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -26,14 +26,6 @@ using namespace boost;
static const int MAX_OUTBOUND_CONNECTIONS = 8;
-void ThreadMessageHandler2(void* parg);
-void ThreadSocketHandler2(void* parg);
-void ThreadOpenConnections2(void* parg);
-void ThreadOpenAddedConnections2(void* parg);
-#ifdef USE_UPNP
-void ThreadMapPort2(void* parg);
-#endif
-void ThreadDNSAddressSeed2(void* parg);
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false);
@@ -46,7 +38,6 @@ struct LocalServiceInfo {
// Global state variables
//
bool fDiscover = true;
-bool fUseUPnP = false;
uint64 nLocalServices = NODE_NETWORK;
static CCriticalSection cs_mapLocalHost;
static map<CNetAddr, LocalServiceInfo> mapLocalHost;
@@ -54,7 +45,6 @@ static bool vfReachable[NET_MAX] = {};
static bool vfLimited[NET_MAX] = {};
static CNode* pnodeLocalHost = NULL;
uint64 nLocalHostNonce = 0;
-array<int, THREAD_MAX> vnThreadsRunning;
static std::vector<SOCKET> vhListenSocket;
CAddrMan addrman;
@@ -63,7 +53,7 @@ CCriticalSection cs_vNodes;
map<CInv, CDataStream> mapRelay;
deque<pair<int64, CInv> > vRelayExpiration;
CCriticalSection cs_mapRelay;
-map<CInv, int64> mapAlreadyAskedFor;
+limitedmap<CInv, int64> mapAlreadyAskedFor(MAX_INV_SZ);
static deque<string> vOneShots;
CCriticalSection cs_vOneShots;
@@ -156,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();
@@ -165,7 +154,7 @@ bool RecvLine(SOCKET hSocket, string& strLine)
continue;
if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
{
- Sleep(10);
+ MilliSleep(10);
continue;
}
}
@@ -754,33 +743,11 @@ void SocketSendData(CNode *pnode)
pnode->vSendMsg.erase(pnode->vSendMsg.begin(), it);
}
-void ThreadSocketHandler(void* parg)
-{
- // Make this thread recognisable as the networking thread
- RenameThread("bitcoin-net");
+static list<CNode*> vNodesDisconnected;
- try
- {
- vnThreadsRunning[THREAD_SOCKETHANDLER]++;
- ThreadSocketHandler2(parg);
- vnThreadsRunning[THREAD_SOCKETHANDLER]--;
- }
- catch (std::exception& e) {
- vnThreadsRunning[THREAD_SOCKETHANDLER]--;
- PrintException(&e, "ThreadSocketHandler()");
- } catch (...) {
- vnThreadsRunning[THREAD_SOCKETHANDLER]--;
- throw; // support pthread_cancel()
- }
- printf("ThreadSocketHandler exited\n");
-}
-
-void ThreadSocketHandler2(void* parg)
+void ThreadSocketHandler()
{
- printf("ThreadSocketHandler started\n");
- list<CNode*> vNodesDisconnected;
unsigned int nPrevNodeCount = 0;
-
loop
{
//
@@ -892,12 +859,10 @@ void ThreadSocketHandler2(void* parg)
}
}
- vnThreadsRunning[THREAD_SOCKETHANDLER]--;
int nSelect = select(have_fds ? hSocketMax + 1 : 0,
&fdsetRecv, &fdsetSend, &fdsetError, &timeout);
- vnThreadsRunning[THREAD_SOCKETHANDLER]++;
- if (fShutdown)
- return;
+ boost::this_thread::interruption_point();
+
if (nSelect == SOCKET_ERROR)
{
if (have_fds)
@@ -909,7 +874,7 @@ void ThreadSocketHandler2(void* parg)
}
FD_ZERO(&fdsetSend);
FD_ZERO(&fdsetError);
- Sleep(timeout.tv_usec/1000);
+ MilliSleep(timeout.tv_usec/1000);
}
@@ -984,8 +949,7 @@ void ThreadSocketHandler2(void* parg)
}
BOOST_FOREACH(CNode* pnode, vNodesCopy)
{
- if (fShutdown)
- return;
+ boost::this_thread::interruption_point();
//
// Receive
@@ -1076,7 +1040,7 @@ void ThreadSocketHandler2(void* parg)
pnode->Release();
}
- Sleep(10);
+ MilliSleep(10);
}
}
@@ -1089,31 +1053,8 @@ void ThreadSocketHandler2(void* parg)
#ifdef USE_UPNP
-void ThreadMapPort(void* parg)
-{
- // Make this thread recognisable as the UPnP thread
- RenameThread("bitcoin-UPnP");
-
- try
- {
- vnThreadsRunning[THREAD_UPNP]++;
- ThreadMapPort2(parg);
- vnThreadsRunning[THREAD_UPNP]--;
- }
- catch (std::exception& e) {
- vnThreadsRunning[THREAD_UPNP]--;
- PrintException(&e, "ThreadMapPort()");
- } catch (...) {
- vnThreadsRunning[THREAD_UPNP]--;
- PrintException(NULL, "ThreadMapPort()");
- }
- printf("ThreadMapPort exited\n");
-}
-
-void ThreadMapPort2(void* parg)
+void ThreadMapPort()
{
- printf("ThreadMapPort started\n");
-
std::string port = strprintf("%u", GetListenPort());
const char * multicastif = 0;
const char * minissdpdpath = 0;
@@ -1154,33 +1095,9 @@ void ThreadMapPort2(void* parg)
}
string strDesc = "Bitcoin " + FormatFullVersion();
-#ifndef UPNPDISCOVER_SUCCESS
- /* miniupnpc 1.5 */
- r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
- port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
-#else
- /* miniupnpc 1.6 */
- r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
- port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
-#endif
- if(r!=UPNPCOMMAND_SUCCESS)
- printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
- port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
- else
- printf("UPnP Port Mapping successful.\n");
- int i = 1;
- loop {
- if (fShutdown || !fUseUPnP)
- {
- r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
- printf("UPNP_DeletePortMapping() returned : %d\n", r);
- freeUPNPDevlist(devlist); devlist = 0;
- FreeUPNPUrls(&urls);
- return;
- }
- if (i % 600 == 0) // Refresh every 20 minutes
- {
+ try {
+ loop {
#ifndef UPNPDISCOVER_SUCCESS
/* miniupnpc 1.5 */
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
@@ -1196,33 +1113,49 @@ void ThreadMapPort2(void* parg)
port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
else
printf("UPnP Port Mapping successful.\n");;
+
+ MilliSleep(20*60*1000); // Refresh every 20 minutes
}
- Sleep(2000);
- i++;
+ }
+ catch (boost::thread_interrupted)
+ {
+ r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
+ printf("UPNP_DeletePortMapping() returned : %d\n", r);
+ freeUPNPDevlist(devlist); devlist = 0;
+ FreeUPNPUrls(&urls);
+ throw;
}
} else {
printf("No valid UPnP IGDs found\n");
freeUPNPDevlist(devlist); devlist = 0;
if (r != 0)
FreeUPNPUrls(&urls);
- loop {
- if (fShutdown || !fUseUPnP)
- return;
- Sleep(2000);
- }
}
}
-void MapPort()
+void MapPort(bool fUseUPnP)
{
- if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
+ static boost::thread* upnp_thread = NULL;
+
+ if (fUseUPnP)
{
- if (!NewThread(ThreadMapPort, NULL))
- printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
+ if (upnp_thread) {
+ upnp_thread->interrupt();
+ upnp_thread->join();
+ delete upnp_thread;
+ }
+ upnp_thread = new boost::thread(boost::bind(&TraceThread<boost::function<void()> >, "upnp", &ThreadMapPort));
+ }
+ else if (upnp_thread) {
+ upnp_thread->interrupt();
+ upnp_thread->join();
+ delete upnp_thread;
+ upnp_thread = NULL;
}
}
+
#else
-void MapPort()
+void MapPort(bool)
{
// Intentionally left blank.
}
@@ -1254,32 +1187,10 @@ static const char *strTestNetDNSSeed[][2] = {
{NULL, NULL}
};
-void ThreadDNSAddressSeed(void* parg)
-{
- // Make this thread recognisable as the DNS seeding thread
- RenameThread("bitcoin-dnsseed");
-
- try
- {
- vnThreadsRunning[THREAD_DNSSEED]++;
- ThreadDNSAddressSeed2(parg);
- vnThreadsRunning[THREAD_DNSSEED]--;
- }
- catch (std::exception& e) {
- vnThreadsRunning[THREAD_DNSSEED]--;
- PrintException(&e, "ThreadDNSAddressSeed()");
- } catch (...) {
- vnThreadsRunning[THREAD_DNSSEED]--;
- throw; // support pthread_cancel()
- }
- printf("ThreadDNSAddressSeed exited\n");
-}
-
-void ThreadDNSAddressSeed2(void* parg)
+void ThreadDNSAddressSeed()
{
static const char *(*strDNSSeed)[2] = fTestNet ? strTestNetDNSSeed : strMainNetDNSSeed;
- printf("ThreadDNSAddressSeed started\n");
int found = 0;
printf("Loading addresses from DNS seeds (could take a while)\n");
@@ -1409,57 +1320,6 @@ void DumpAddresses()
addrman.size(), GetTimeMillis() - nStart);
}
-void ThreadDumpAddress2(void* parg)
-{
- printf("ThreadDumpAddress started\n");
-
- vnThreadsRunning[THREAD_DUMPADDRESS]++;
- while (!fShutdown)
- {
- DumpAddresses();
- vnThreadsRunning[THREAD_DUMPADDRESS]--;
- Sleep(100000);
- vnThreadsRunning[THREAD_DUMPADDRESS]++;
- }
- vnThreadsRunning[THREAD_DUMPADDRESS]--;
-}
-
-void ThreadDumpAddress(void* parg)
-{
- // Make this thread recognisable as the address dumping thread
- RenameThread("bitcoin-adrdump");
-
- try
- {
- ThreadDumpAddress2(parg);
- }
- catch (std::exception& e) {
- PrintException(&e, "ThreadDumpAddress()");
- }
- printf("ThreadDumpAddress exited\n");
-}
-
-void ThreadOpenConnections(void* parg)
-{
- // Make this thread recognisable as the connection opening thread
- RenameThread("bitcoin-opencon");
-
- try
- {
- vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
- ThreadOpenConnections2(parg);
- vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
- }
- catch (std::exception& e) {
- vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
- PrintException(&e, "ThreadOpenConnections()");
- } catch (...) {
- vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
- PrintException(NULL, "ThreadOpenConnections()");
- }
- printf("ThreadOpenConnections exited\n");
-}
-
void static ProcessOneShot()
{
string strDest;
@@ -1478,10 +1338,8 @@ void static ProcessOneShot()
}
}
-void ThreadOpenConnections2(void* parg)
+void ThreadOpenConnections()
{
- printf("ThreadOpenConnections started\n");
-
// Connect to specific addresses
if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
{
@@ -1494,12 +1352,10 @@ void ThreadOpenConnections2(void* parg)
OpenNetworkConnection(addr, NULL, strAddr.c_str());
for (int i = 0; i < 10 && i < nLoop; i++)
{
- Sleep(500);
- if (fShutdown)
- return;
+ MilliSleep(500);
}
}
- Sleep(500);
+ MilliSleep(500);
}
}
@@ -1509,18 +1365,10 @@ void ThreadOpenConnections2(void* parg)
{
ProcessOneShot();
- vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
- Sleep(500);
- vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
- if (fShutdown)
- return;
-
+ MilliSleep(500);
- vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
CSemaphoreGrant grant(*semOutbound);
- vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
- if (fShutdown)
- return;
+ boost::this_thread::interruption_point();
// Add seed nodes if IRC isn't working
if (addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
@@ -1600,38 +1448,15 @@ void ThreadOpenConnections2(void* parg)
}
}
-void ThreadOpenAddedConnections(void* parg)
+void ThreadOpenAddedConnections()
{
- // Make this thread recognisable as the connection opening thread
- RenameThread("bitcoin-opencon");
-
- try
- {
- vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
- ThreadOpenAddedConnections2(parg);
- vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
- }
- catch (std::exception& e) {
- vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
- PrintException(&e, "ThreadOpenAddedConnections()");
- } catch (...) {
- vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
- PrintException(NULL, "ThreadOpenAddedConnections()");
- }
- printf("ThreadOpenAddedConnections exited\n");
-}
-
-void ThreadOpenAddedConnections2(void* parg)
-{
- printf("ThreadOpenAddedConnections started\n");
-
{
LOCK(cs_vAddedNodes);
vAddedNodes = mapMultiArgs["-addnode"];
}
if (HaveNameProxy()) {
- while(!fShutdown) {
+ while(true) {
list<string> lAddresses(0);
{
LOCK(cs_vAddedNodes);
@@ -1642,15 +1467,10 @@ void ThreadOpenAddedConnections2(void* parg)
CAddress addr;
CSemaphoreGrant grant(*semOutbound);
OpenNetworkConnection(addr, &grant, strAddNode.c_str());
- Sleep(500);
- if (fShutdown)
- return;
+ MilliSleep(500);
}
- vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
- Sleep(120000); // Retry every 2 minutes
- vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
+ MilliSleep(120000); // Retry every 2 minutes
}
- return;
}
for (unsigned int i = 0; true; i++)
@@ -1694,17 +1514,9 @@ void ThreadOpenAddedConnections2(void* parg)
{
CSemaphoreGrant grant(*semOutbound);
OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
- Sleep(500);
- if (fShutdown)
- return;
+ MilliSleep(500);
}
- if (fShutdown)
- return;
- vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
- Sleep(120000); // Retry every 2 minutes
- vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
- if (fShutdown)
- return;
+ MilliSleep(120000); // Retry every 2 minutes
}
}
@@ -1714,8 +1526,7 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu
//
// Initiate outbound network connection
//
- if (fShutdown)
- return false;
+ boost::this_thread::interruption_point();
if (!strDest)
if (IsLocal(addrConnect) ||
FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
@@ -1724,11 +1535,9 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu
if (strDest && FindNode(strDest))
return false;
- vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
CNode* pnode = ConnectNode(addrConnect, strDest);
- vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
- if (fShutdown)
- return false;
+ boost::this_thread::interruption_point();
+
if (!pnode)
return false;
if (grantOutbound)
@@ -1746,33 +1555,10 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu
-
-void ThreadMessageHandler(void* parg)
+void ThreadMessageHandler()
{
- // Make this thread recognisable as the message handling thread
- RenameThread("bitcoin-msghand");
-
- try
- {
- vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
- ThreadMessageHandler2(parg);
- vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
- }
- catch (std::exception& e) {
- vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
- PrintException(&e, "ThreadMessageHandler()");
- } catch (...) {
- vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
- PrintException(NULL, "ThreadMessageHandler()");
- }
- printf("ThreadMessageHandler exited\n");
-}
-
-void ThreadMessageHandler2(void* parg)
-{
- printf("ThreadMessageHandler started\n");
SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
- while (!fShutdown)
+ while (true)
{
vector<CNode*> vNodesCopy;
{
@@ -1798,8 +1584,7 @@ void ThreadMessageHandler2(void* parg)
if (!ProcessMessages(pnode))
pnode->CloseSocketDisconnect();
}
- if (fShutdown)
- return;
+ boost::this_thread::interruption_point();
// Send messages
{
@@ -1807,8 +1592,7 @@ void ThreadMessageHandler2(void* parg)
if (lockSend)
SendMessages(pnode, pnode == pnodeTrickle);
}
- if (fShutdown)
- return;
+ boost::this_thread::interruption_point();
}
{
@@ -1817,16 +1601,7 @@ void ThreadMessageHandler2(void* parg)
pnode->Release();
}
- // Wait and allow messages to bunch up.
- // Reduce vnThreadsRunning so StopNode has permission to exit while
- // we're sleeping, but we must always check fShutdown after doing this.
- vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
- Sleep(100);
- if (fRequestShutdown)
- StartShutdown();
- vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
- if (fShutdown)
- return;
+ MilliSleep(100);
}
}
@@ -1998,7 +1773,7 @@ void static Discover()
NewThread(ThreadGetMyExternalIP, NULL);
}
-void StartNode(void* parg)
+void StartNode(boost::thread_group& threadGroup)
{
// Make this thread recognisable as the startup thread
RenameThread("bitcoin-start");
@@ -2021,73 +1796,41 @@ void StartNode(void* parg)
if (!GetBoolArg("-dnsseed", true))
printf("DNS seeding disabled\n");
else
- if (!NewThread(ThreadDNSAddressSeed, NULL))
- printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
+ threadGroup.create_thread(boost::bind(&TraceThread<boost::function<void()> >, "dnsseed", &ThreadDNSAddressSeed));
+#ifdef USE_UPNP
// Map ports with UPnP
- if (fUseUPnP)
- MapPort();
+ MapPort(GetBoolArg("-upnp", USE_UPNP));
+#endif
// Send and receive from sockets, accept connections
- if (!NewThread(ThreadSocketHandler, NULL))
- printf("Error: NewThread(ThreadSocketHandler) failed\n");
+ threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "net", &ThreadSocketHandler));
// Initiate outbound connections from -addnode
- if (!NewThread(ThreadOpenAddedConnections, NULL))
- printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
+ threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "addcon", &ThreadOpenAddedConnections));
// Initiate outbound connections
- if (!NewThread(ThreadOpenConnections, NULL))
- printf("Error: NewThread(ThreadOpenConnections) failed\n");
+ threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "opencon", &ThreadOpenConnections));
// Process messages
- if (!NewThread(ThreadMessageHandler, NULL))
- printf("Error: NewThread(ThreadMessageHandler) failed\n");
+ threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "msghand", &ThreadMessageHandler));
// Dump network addresses
- if (!NewThread(ThreadDumpAddress, NULL))
- printf("Error; NewThread(ThreadDumpAddress) failed\n");
-
- // Generate coins in the background
- GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain);
+ threadGroup.create_thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 10000));
}
bool StopNode()
{
printf("StopNode()\n");
- fShutdown = true;
+ GenerateBitcoins(false, NULL);
+ MapPort(false);
nTransactionsUpdated++;
- int64 nStart = GetTime();
if (semOutbound)
for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
semOutbound->post();
- do
- {
- int nThreadsRunning = 0;
- for (int n = 0; n < THREAD_MAX; n++)
- nThreadsRunning += vnThreadsRunning[n];
- if (nThreadsRunning == 0)
- break;
- if (GetTime() - nStart > 20)
- break;
- Sleep(20);
- } while(true);
- if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler 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_MINER] > 0) printf("ThreadBitcoinMiner still running\n");
- if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
- if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
-#ifdef USE_UPNP
- if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
-#endif
- if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
- if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
- if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
- while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0)
- Sleep(20);
- Sleep(50);
+ MilliSleep(50);
DumpAddresses();
+
return true;
}
@@ -2108,6 +1851,18 @@ public:
if (closesocket(hListenSocket) == SOCKET_ERROR)
printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
+ // clean up some globals (to help leak detection)
+ BOOST_FOREACH(CNode *pnode, vNodes)
+ delete pnode;
+ BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
+ delete pnode;
+ vNodes.clear();
+ vNodesDisconnected.clear();
+ delete semOutbound;
+ semOutbound = NULL;
+ delete pnodeLocalHost;
+ pnodeLocalHost = NULL;
+
#ifdef WIN32
// Shutdown Windows Sockets
WSACleanup();
diff --git a/src/net.h b/src/net.h
index 368e4cd4bb..30b9ac8663 100644
--- a/src/net.h
+++ b/src/net.h
@@ -15,6 +15,7 @@
#endif
#include "mruset.h"
+#include "limitedmap.h"
#include "netbase.h"
#include "protocol.h"
#include "addrman.h"
@@ -37,10 +38,10 @@ void AddressCurrentlyConnected(const CService& addr);
CNode* FindNode(const CNetAddr& ip);
CNode* FindNode(const CService& ip);
CNode* ConnectNode(CAddress addrConnect, const char *strDest = NULL, int64 nTimeout=0);
-void MapPort();
+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,30 +70,9 @@ void SetReachable(enum Network net, bool fFlag = true);
CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL);
-/** Thread types */
-enum threadId
-{
- THREAD_SOCKETHANDLER,
- THREAD_OPENCONNECTIONS,
- THREAD_MESSAGEHANDLER,
- THREAD_MINER,
- THREAD_RPCLISTENER,
- THREAD_UPNP,
- THREAD_DNSSEED,
- THREAD_ADDEDCONNECTIONS,
- THREAD_DUMPADDRESS,
- THREAD_RPCHANDLER,
- THREAD_IMPORT,
- THREAD_SCRIPTCHECK,
-
- THREAD_MAX
-};
-
extern bool fDiscover;
-extern bool fUseUPnP;
extern uint64 nLocalServices;
extern uint64 nLocalHostNonce;
-extern boost::array<int, THREAD_MAX> vnThreadsRunning;
extern CAddrMan addrman;
extern std::vector<CNode*> vNodes;
@@ -100,7 +80,7 @@ extern CCriticalSection cs_vNodes;
extern std::map<CInv, CDataStream> mapRelay;
extern std::deque<std::pair<int64, CInv> > vRelayExpiration;
extern CCriticalSection cs_mapRelay;
-extern std::map<CInv, int64> mapAlreadyAskedFor;
+extern limitedmap<CInv, int64> mapAlreadyAskedFor;
extern std::vector<std::string> vAddedNodes;
extern CCriticalSection cs_vAddedNodes;
@@ -367,7 +347,12 @@ public:
{
// We're using mapAskFor as a priority queue,
// the key is the earliest time the request can be sent
- int64& nRequestTime = mapAlreadyAskedFor[inv];
+ int64 nRequestTime;
+ limitedmap<CInv, int64>::const_iterator it = mapAlreadyAskedFor.find(inv);
+ if (it != mapAlreadyAskedFor.end())
+ nRequestTime = it->second;
+ else
+ nRequestTime = 0;
if (fDebugNet)
printf("askfor %s %"PRI64d" (%s)\n", inv.ToString().c_str(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str());
@@ -380,6 +365,10 @@ public:
// Each retry is 2 minutes after the last
nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
+ if (it != mapAlreadyAskedFor.end())
+ mapAlreadyAskedFor.update(it, nRequestTime);
+ else
+ mapAlreadyAskedFor.insert(std::make_pair(inv, nRequestTime));
mapAskFor.insert(std::make_pair(nRequestTime, inv));
}
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 346128c0c4..f079f3b0e9 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -11,6 +11,7 @@
#include "guiutil.h"
#include "guiconstants.h"
#include "init.h"
+#include "util.h"
#include "ui_interface.h"
#include "paymentserver.h"
@@ -82,16 +83,11 @@ static void InitMessage(const std::string &message)
if(splashref)
{
splashref->showMessage(QString::fromStdString(message), Qt::AlignBottom|Qt::AlignHCenter, QColor(255,255,200));
- QApplication::instance()->processEvents();
+ qApp->processEvents();
}
printf("init message: %s\n", message.c_str());
}
-static void QueueShutdown()
-{
- QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
-}
-
/*
Translate string to current locale using Qt.
*/
@@ -185,7 +181,6 @@ int main(int argc, char *argv[])
uiInterface.ThreadSafeMessageBox.connect(ThreadSafeMessageBox);
uiInterface.ThreadSafeAskFee.connect(ThreadSafeAskFee);
uiInterface.InitMessage.connect(InitMessage);
- uiInterface.QueueShutdown.connect(QueueShutdown);
uiInterface.Translate.connect(Translate);
// Show help message immediately after parsing command-line options (for "-lang") and setting locale,
@@ -215,9 +210,16 @@ int main(int argc, char *argv[])
if (GUIUtil::GetStartOnSystemStartup())
GUIUtil::SetStartOnSystemStartup(true);
+ boost::thread_group threadGroup;
+
BitcoinGUI window;
guiref = &window;
- if(AppInit2())
+
+ QTimer* pollShutdownTimer = new QTimer(guiref);
+ QObject::connect(pollShutdownTimer, SIGNAL(timeout()), guiref, SLOT(detectShutdown()));
+ pollShutdownTimer->start(200);
+
+ if(AppInit2(threadGroup))
{
{
// Put this in a block, so that the Model objects are cleaned up before
@@ -258,7 +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/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp
index 4fa2ca508b..b12e296f99 100644
--- a/src/qt/bitcoinamountfield.cpp
+++ b/src/qt/bitcoinamountfield.cpp
@@ -98,7 +98,7 @@ bool BitcoinAmountField::eventFilter(QObject *object, QEvent *event)
{
// Translate a comma into a period
QKeyEvent periodKeyEvent(event->type(), Qt::Key_Period, keyEvent->modifiers(), ".", keyEvent->isAutoRepeat(), keyEvent->count());
- qApp->sendEvent(object, &periodKeyEvent);
+ QApplication::sendEvent(object, &periodKeyEvent);
return true;
}
}
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 1c9094a88c..9da5b85006 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -24,6 +24,7 @@
#include "rpcconsole.h"
#include "ui_interface.h"
#include "wallet.h"
+#include "init.h"
#ifdef Q_OS_MAC
#include "macdockiconhandler.h"
@@ -56,7 +57,7 @@
const QString BitcoinGUI::DEFAULT_WALLET = "~Default";
-BitcoinGUI::BitcoinGUI(QWidget *parent):
+BitcoinGUI::BitcoinGUI(QWidget *parent) :
QMainWindow(parent),
clientModel(0),
encryptWalletAction(0),
@@ -70,7 +71,7 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
restoreWindowGeometry();
setWindowTitle(tr("Bitcoin") + " - " + tr("Wallet"));
#ifndef Q_OS_MAC
- qApp->setWindowIcon(QIcon(":icons/bitcoin"));
+ QApplication::setWindowIcon(QIcon(":icons/bitcoin"));
setWindowIcon(QIcon(":icons/bitcoin"));
#else
setUnifiedTitleAndToolBarOnMac(true);
@@ -94,7 +95,7 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
// Create wallet frame and make it the central widget
walletFrame = new WalletFrame(this);
setCentralWidget(walletFrame);
-
+
// Create status bar
statusBar();
@@ -127,7 +128,7 @@ BitcoinGUI::BitcoinGUI(QWidget *parent):
// Override style sheet for progress bar for styles that have a segmented progress bar,
// as they make the text unreadable (workaround for issue #1071)
// See https://qt-project.org/doc/qt-4.8/gallery.html
- QString curStyle = qApp->style()->metaObject()->className();
+ QString curStyle = QApplication::style()->metaObject()->className();
if(curStyle == "QWindowsStyle" || curStyle == "QWindowsXPStyle")
{
progressBar->setStyleSheet("QProgressBar { background-color: #e8e8e8; border: 1px solid grey; border-radius: 7px; padding: 1px; text-align: center; } QProgressBar::chunk { background: QLinearGradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 #FF8000, stop: 1 orange); border-radius: 7px; margin: 0px; }");
@@ -221,6 +222,7 @@ void BitcoinGUI::createActions()
optionsAction->setMenuRole(QAction::PreferencesRole);
toggleHideAction = new QAction(QIcon(":/icons/bitcoin"), tr("&Show / Hide"), this);
toggleHideAction->setStatusTip(tr("Show or hide the main Window"));
+
encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this);
encryptWalletAction->setStatusTip(tr("Encrypt the private keys that belong to your wallet"));
encryptWalletAction->setCheckable(true);
@@ -308,7 +310,7 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
{
setWindowTitle(windowTitle() + QString(" ") + tr("[testnet]"));
#ifndef Q_OS_MAC
- qApp->setWindowIcon(QIcon(":icons/bitcoin_testnet"));
+ QApplication::setWindowIcon(QIcon(":icons/bitcoin_testnet"));
setWindowIcon(QIcon(":icons/bitcoin_testnet"));
#else
MacDockIconHandler::instance()->setIcon(QIcon(":icons/bitcoin_testnet"));
@@ -368,7 +370,7 @@ void BitcoinGUI::createTrayIcon()
trayIcon->show();
#endif
- notificator = new Notificator(qApp->applicationName(), trayIcon);
+ notificator = new Notificator(QApplication::applicationName(), trayIcon);
}
void BitcoinGUI::createTrayIconMenu()
@@ -432,7 +434,7 @@ void BitcoinGUI::restoreWindowGeometry()
QSize size = settings.value("nWindowSize", QSize(850, 550)).toSize();
if (!pos.x() && !pos.y())
{
- QRect screen = qApp->desktop()->screenGeometry();
+ QRect screen = QApplication::desktop()->screenGeometry();
pos.setX((screen.width()-size.width())/2);
pos.setY((screen.height()-size.height())/2);
}
@@ -488,7 +490,7 @@ void BitcoinGUI::gotoSignMessageTab(QString addr)
void BitcoinGUI::gotoVerifyMessageTab(QString addr)
{
- if (walletFrame) walletFrame->gotoSignMessageTab(addr);
+ if (walletFrame) walletFrame->gotoVerifyMessageTab(addr);
}
void BitcoinGUI::setNumConnections(int count)
@@ -681,7 +683,7 @@ void BitcoinGUI::closeEvent(QCloseEvent *event)
if(!clientModel->getOptionsModel()->getMinimizeToTray() &&
!clientModel->getOptionsModel()->getMinimizeOnClose())
{
- qApp->quit();
+ QApplication::quit();
}
#endif
}
@@ -838,3 +840,9 @@ void BitcoinGUI::toggleHidden()
{
showNormalIfMinimized(true);
}
+
+void BitcoinGUI::detectShutdown()
+{
+ if (ShutdownRequested())
+ QMetaObject::invokeMethod(QCoreApplication::instance(), "quit", Qt::QueuedConnection);
+}
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index c0cde97b6a..aba81cb3bc 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -29,6 +29,7 @@ class QStackedWidget;
class QUrl;
class QListWidget;
class QPushButton;
+class QAction;
QT_END_NAMESPACE
/**
@@ -41,7 +42,7 @@ class BitcoinGUI : public QMainWindow
public:
static const QString DEFAULT_WALLET;
-
+
explicit BitcoinGUI(QWidget *parent = 0);
~BitcoinGUI();
@@ -56,9 +57,17 @@ public:
bool addWallet(const QString& name, WalletModel *walletModel);
bool setCurrentWallet(const QString& name);
-
+
void removeAllWallets();
+ /** Used by WalletView to allow access to needed QActions */
+ QAction * getOverviewAction() { return overviewAction; }
+ QAction * getHistoryAction() { return historyAction; }
+ QAction * getAddressBookAction() { return addressBookAction; }
+ QAction * getReceiveCoinsAction() { return receiveCoinsAction; }
+ QAction * getSendCoinsAction() { return sendCoinsAction; }
+ QAction * getExportAction() { return exportAction; }
+
protected:
void changeEvent(QEvent *e);
void closeEvent(QCloseEvent *event);
@@ -190,6 +199,9 @@ private slots:
void showNormalIfMinimized(bool fToggleHidden = false);
/** Simply calls showNormalIfMinimized(true) for use in SLOT() macro */
void toggleHidden();
+
+ /** called by a timer to check if fRequestShutdown has been set **/
+ void detectShutdown();
};
#endif // BITCOINGUI_H
diff --git a/src/qt/bitcoinstrings.cpp b/src/qt/bitcoinstrings.cpp
index 328e3af9ef..2c500f4fe1 100644
--- a/src/qt/bitcoinstrings.cpp
+++ b/src/qt/bitcoinstrings.cpp
@@ -8,14 +8,16 @@
static const char UNUSED *bitcoin_strings[] = {
QT_TRANSLATE_NOOP("bitcoin-core", ""
"%s, you must set a rpcpassword in the configuration file:\n"
-" %s\n"
+"%s\n"
"It is recommended you use the following random password:\n"
"rpcuser=bitcoinrpc\n"
"rpcpassword=%s\n"
"(you do not need to remember this password)\n"
"The username and password MUST NOT be the same.\n"
"If the file does not exist, create it with owner-readable-only file "
-"permissions.\n"),
+"permissions.\n"
+"It is also recommended to set alertnotify so you are notified of problems;\n"
+"for example: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" admin@foo.com\n"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
"Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:"
"@STRENGTH)"),
@@ -41,6 +43,9 @@ QT_TRANSLATE_NOOP("bitcoin-core", ""
"Error: This transaction requires a transaction fee of at least %s because of "
"its amount, complexity, or use of recently received funds!"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
+"Execute command when a relevant alert is received (%s in cmd is replaced by "
+"message)"),
+QT_TRANSLATE_NOOP("bitcoin-core", ""
"Execute command when a wallet transaction changes (%s in cmd is replaced by "
"TxID)"),
QT_TRANSLATE_NOOP("bitcoin-core", ""
@@ -129,7 +134,6 @@ QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write transaction index"),
QT_TRANSLATE_NOOP("bitcoin-core", "Failed to write undo data"),
QT_TRANSLATE_NOOP("bitcoin-core", "Fee per KB to add to transactions you send"),
QT_TRANSLATE_NOOP("bitcoin-core", "Find peers using DNS lookup (default: 1 unless -connect)"),
-QT_TRANSLATE_NOOP("bitcoin-core", "Find peers using internet relay chat (default: 0)"),
QT_TRANSLATE_NOOP("bitcoin-core", "Generate coins"),
QT_TRANSLATE_NOOP("bitcoin-core", "Get help for a command"),
QT_TRANSLATE_NOOP("bitcoin-core", "How many blocks to check at startup (default: 288, 0 = all)"),
diff --git a/src/qt/guiutil.cpp b/src/qt/guiutil.cpp
index 06ccde3782..2105f0730e 100644
--- a/src/qt/guiutil.cpp
+++ b/src/qt/guiutil.cpp
@@ -160,8 +160,10 @@ void copyEntryData(QAbstractItemView *view, int column, int role)
if(!selection.isEmpty())
{
- // Copy first item
- QApplication::clipboard()->setText(selection.at(0).data(role).toString(),QClipboard::Selection);
+ // Copy first item (global clipboard)
+ QApplication::clipboard()->setText(selection.at(0).data(role).toString(), QClipboard::Clipboard);
+ // Copy first item (global mouse selection for e.g. X11 - NOP on Windows)
+ QApplication::clipboard()->setText(selection.at(0).data(role).toString(), QClipboard::Selection);
}
}
@@ -213,7 +215,7 @@ QString getSaveFileName(QWidget *parent, const QString &caption,
Qt::ConnectionType blockingGUIThreadConnection()
{
- if(QThread::currentThread() != QCoreApplication::instance()->thread())
+ if(QThread::currentThread() != qApp->thread())
{
return Qt::BlockingQueuedConnection;
}
@@ -225,7 +227,7 @@ Qt::ConnectionType blockingGUIThreadConnection()
bool checkPoint(const QPoint &p, const QWidget *w)
{
- QWidget *atW = qApp->widgetAt(w->mapToGlobal(p));
+ QWidget *atW = QApplication::widgetAt(w->mapToGlobal(p));
if (!atW) return false;
return atW->topLevelWidget() == w;
}
@@ -457,4 +459,3 @@ void HelpMessageBox::showOrPrint()
}
} // namespace GUIUtil
-
diff --git a/src/qt/locale/bitcoin_en.ts b/src/qt/locale/bitcoin_en.ts
index 806a72655e..c74b11d3d6 100644
--- a/src/qt/locale/bitcoin_en.ts
+++ b/src/qt/locale/bitcoin_en.ts
@@ -310,17 +310,17 @@ This product includes software developed by the OpenSSL Project for use in the O
<context>
<name>BitcoinGUI</name>
<message>
- <location filename="../bitcoingui.cpp" line="+269"/>
+ <location filename="../bitcoingui.cpp" line="+231"/>
<source>Sign &amp;message...</source>
<translation>Sign &amp;message...</translation>
</message>
<message>
- <location line="+254"/>
+ <location line="+299"/>
<source>Synchronizing with network...</source>
<translation>Synchronizing with network...</translation>
</message>
<message>
- <location line="-322"/>
+ <location line="-367"/>
<source>&amp;Overview</source>
<translation>&amp;Overview</translation>
</message>
@@ -340,32 +340,17 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Browse transaction history</translation>
</message>
<message>
- <location line="+6"/>
- <source>&amp;Address Book</source>
- <translation>&amp;Address Book</translation>
- </message>
- <message>
- <location line="+1"/>
+ <location line="+7"/>
<source>Edit the list of stored addresses and labels</source>
<translation>Edit the list of stored addresses and labels</translation>
</message>
<message>
- <location line="-15"/>
- <source>&amp;Receive coins</source>
- <translation>&amp;Receive coins</translation>
- </message>
- <message>
- <location line="+1"/>
+ <location line="-14"/>
<source>Show the list of addresses for receiving payments</source>
<translation>Show the list of addresses for receiving payments</translation>
</message>
<message>
- <location line="-8"/>
- <source>&amp;Send coins</source>
- <translation>&amp;Send coins</translation>
- </message>
- <message>
- <location line="+39"/>
+ <location line="+31"/>
<source>E&amp;xit</source>
<translation>E&amp;xit</translation>
</message>
@@ -410,7 +395,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>&amp;Change Passphrase...</translation>
</message>
<message>
- <location line="+259"/>
+ <location line="+304"/>
<source>Importing blocks from disk...</source>
<translation>Importing blocks from disk...</translation>
</message>
@@ -420,7 +405,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Reindexing blocks on disk...</translation>
</message>
<message>
- <location line="-255"/>
+ <location line="-300"/>
<source>&amp;Export...</source>
<translation>&amp;Export...</translation>
</message>
@@ -465,18 +450,33 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>&amp;Verify message...</translation>
</message>
<message>
- <location line="-198"/>
- <location line="+531"/>
+ <location line="-162"/>
+ <location line="+540"/>
<source>Bitcoin</source>
<translation>Bitcoin</translation>
</message>
<message>
- <location line="-531"/>
+ <location line="-540"/>
<source>Wallet</source>
<translation>Wallet</translation>
</message>
<message>
- <location line="+178"/>
+ <location line="+99"/>
+ <source>&amp;Send</source>
+ <translation>&amp;Send</translation>
+ </message>
+ <message>
+ <location line="+7"/>
+ <source>&amp;Receive</source>
+ <translation>&amp;Receive</translation>
+ </message>
+ <message>
+ <location line="+14"/>
+ <source>&amp;Addresses</source>
+ <translation>&amp;Addresses</translation>
+ </message>
+ <message>
+ <location line="+22"/>
<source>&amp;About Bitcoin</source>
<translation>&amp;About Bitcoin</translation>
</message>
@@ -537,12 +537,12 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>[testnet]</translation>
</message>
<message>
- <location line="+63"/>
+ <location line="+47"/>
<source>Bitcoin client</source>
<translation>Bitcoin client</translation>
</message>
<message numerus="yes">
- <location line="+79"/>
+ <location line="+140"/>
<source>%n active connection(s) to Bitcoin network</source>
<translation>
<numerusform>%n active connection to Bitcoin network</numerusform>
@@ -619,17 +619,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee?</translation>
</message>
<message>
- <location line="+213"/>
- <source>Backup Successful</source>
- <translation>Backup Successful</translation>
- </message>
- <message>
- <location line="+0"/>
- <source>The wallet data was successfully saved to the new location.</source>
- <translation>The wallet data was successfully saved to the new location.</translation>
- </message>
- <message>
- <location line="-351"/>
+ <location line="-138"/>
<source>Up to date</source>
<translation>Up to date</translation>
</message>
@@ -644,7 +634,7 @@ This product includes software developed by the OpenSSL Project for use in the O
<translation>Confirm transaction fee</translation>
</message>
<message>
- <location line="+23"/>
+ <location line="+8"/>
<source>Sent transaction</source>
<translation>Sent transaction</translation>
</message>
@@ -667,14 +657,14 @@ Address: %4
</translation>
</message>
<message>
- <location line="+102"/>
- <location line="+28"/>
+ <location line="+33"/>
+ <location line="+23"/>
<source>URI handling</source>
<translation>URI handling</translation>
</message>
<message>
- <location line="-28"/>
- <location line="+28"/>
+ <location line="-23"/>
+ <location line="+23"/>
<source>URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</source>
<translation>URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters.</translation>
</message>
@@ -689,26 +679,6 @@ Address: %4
<translation>Wallet is &lt;b&gt;encrypted&lt;/b&gt; and currently &lt;b&gt;locked&lt;/b&gt;</translation>
</message>
<message>
- <location line="+23"/>
- <source>Backup Wallet</source>
- <translation>Backup Wallet</translation>
- </message>
- <message>
- <location line="+0"/>
- <source>Wallet Data (*.dat)</source>
- <translation>Wallet Data (*.dat)</translation>
- </message>
- <message>
- <location line="+3"/>
- <source>Backup Failed</source>
- <translation>Backup Failed</translation>
- </message>
- <message>
- <location line="+0"/>
- <source>There was an error trying to save the wallet data to the new location.</source>
- <translation>There was an error trying to save the wallet data to the new location.</translation>
- </message>
- <message>
<location filename="../bitcoin.cpp" line="+108"/>
<source>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</source>
<translation>A fatal error occurred. Bitcoin can no longer continue safely and will quit.</translation>
@@ -1052,23 +1022,18 @@ Address: %4
<translation>Form</translation>
</message>
<message>
- <location line="+51"/>
- <location line="+183"/>
+ <location line="+50"/>
+ <location line="+166"/>
<source>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</source>
<translation>The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet.</translation>
</message>
<message>
- <location line="-141"/>
+ <location line="-124"/>
<source>Balance:</source>
<translation>Balance:</translation>
</message>
<message>
- <location line="+58"/>
- <source>Number of transactions:</source>
- <translation>Number of transactions:</translation>
- </message>
- <message>
- <location line="-29"/>
+ <location line="+29"/>
<source>Unconfirmed:</source>
<translation>Unconfirmed:</translation>
</message>
@@ -1078,7 +1043,7 @@ Address: %4
<translation>Wallet</translation>
</message>
<message>
- <location line="+124"/>
+ <location line="+107"/>
<source>Immature:</source>
<translation>Immature:</translation>
</message>
@@ -1093,7 +1058,7 @@ Address: %4
<translation>&lt;b&gt;Recent transactions&lt;/b&gt;</translation>
</message>
<message>
- <location line="-118"/>
+ <location line="-101"/>
<source>Your current balance</source>
<translation>Your current balance</translation>
</message>
@@ -1103,11 +1068,6 @@ Address: %4
<translation>Total of transactions that have yet to be confirmed, and do not yet count toward the current balance</translation>
</message>
<message>
- <location line="+20"/>
- <source>Total number of transactions in wallet</source>
- <translation>Total number of transactions in wallet</translation>
- </message>
- <message>
<location filename="../overviewpage.cpp" line="+115"/>
<location line="+1"/>
<source>out of sync</source>
@@ -2104,6 +2064,11 @@ Address: %4
</message>
<message>
<location line="+1"/>
+ <source>Copy transaction ID</source>
+ <translation>Copy transaction ID</translation>
+ </message>
+ <message>
+ <location line="+1"/>
<source>Edit label</source>
<translation>Edit label</translation>
</message>
@@ -2113,7 +2078,7 @@ Address: %4
<translation>Show transaction details</translation>
</message>
<message>
- <location line="+137"/>
+ <location line="+139"/>
<source>Export Transaction Data</source>
<translation>Export Transaction Data</translation>
</message>
@@ -2168,7 +2133,7 @@ Address: %4
<translation>Could not write to file %1.</translation>
</message>
<message>
- <location line="+95"/>
+ <location line="+100"/>
<source>Range:</source>
<translation>Range:</translation>
</message>
@@ -2179,14 +2144,157 @@ Address: %4
</message>
</context>
<context>
+ <name>WalletView</name>
+ <message>
+ <location filename="../walletview.cpp" line="+95"/>
+ <source>&amp;Overview</source>
+ <translation>&amp;Overview</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Show general overview of wallet</source>
+ <translation>Show general overview of wallet</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>&amp;Send coins</source>
+ <translation>&amp;Send coins</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Send coins to a Bitcoin address</source>
+ <translation>Send coins to a Bitcoin address</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>&amp;Receive coins</source>
+ <translation>&amp;Receive coins</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Show the list of addresses for receiving payments</source>
+ <translation>Show the list of addresses for receiving payments</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>&amp;Transactions</source>
+ <translation>&amp;Transactions</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Browse transaction history</source>
+ <translation>Browse transaction history</translation>
+ </message>
+ <message>
+ <location line="+6"/>
+ <source>&amp;Address Book</source>
+ <translation>&amp;Address Book</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Edit the list of stored addresses and labels</source>
+ <translation>Edit the list of stored addresses and labels</translation>
+ </message>
+ <message>
+ <location line="+12"/>
+ <source>&amp;Encrypt Wallet...</source>
+ <translation>&amp;Encrypt Wallet...</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Encrypt the private keys that belong to your wallet</source>
+ <translation>Encrypt the private keys that belong to your wallet</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>&amp;Backup Wallet...</source>
+ <translation>&amp;Backup Wallet...</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Backup wallet to another location</source>
+ <translation>Backup wallet to another location</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>&amp;Change Passphrase...</source>
+ <translation>&amp;Change Passphrase...</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Change the passphrase used for wallet encryption</source>
+ <translation>Change the passphrase used for wallet encryption</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Sign &amp;message...</source>
+ <translation>Sign &amp;message...</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Sign messages with your Bitcoin addresses to prove you own them</source>
+ <translation>Sign messages with your Bitcoin addresses to prove you own them</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>&amp;Verify message...</source>
+ <translation>&amp;Verify message...</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Verify messages to ensure they were signed with specified Bitcoin addresses</source>
+ <translation>Verify messages to ensure they were signed with specified Bitcoin addresses</translation>
+ </message>
+ <message>
+ <location line="+2"/>
+ <source>&amp;Export...</source>
+ <translation>&amp;Export...</translation>
+ </message>
+ <message>
+ <location line="+1"/>
+ <source>Export the data in the current tab to a file</source>
+ <translation>Export the data in the current tab to a file</translation>
+ </message>
+ <message>
+ <location line="+180"/>
+ <source>Backup Wallet</source>
+ <translation>Backup Wallet</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>Wallet Data (*.dat)</source>
+ <translation>Wallet Data (*.dat)</translation>
+ </message>
+ <message>
+ <location line="+3"/>
+ <source>Backup Failed</source>
+ <translation>Backup Failed</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>There was an error trying to save the wallet data to the new location.</source>
+ <translation>There was an error trying to save the wallet data to the new location.</translation>
+ </message>
+ <message>
+ <location line="+4"/>
+ <source>Backup Successful</source>
+ <translation>Backup Successful</translation>
+ </message>
+ <message>
+ <location line="+0"/>
+ <source>The wallet data was successfully saved to the new location.</source>
+ <translation>The wallet data was successfully saved to the new location.</translation>
+ </message>
+</context>
+<context>
<name>bitcoin-core</name>
<message>
- <location filename="../bitcoinstrings.cpp" line="+91"/>
+ <location filename="../bitcoinstrings.cpp" line="+96"/>
<source>Bitcoin version</source>
<translation>Bitcoin version</translation>
</message>
<message>
- <location line="+99"/>
+ <location line="+98"/>
<source>Usage:</source>
<translation>Usage:</translation>
</message>
@@ -2226,12 +2334,12 @@ Address: %4
<translation>Generate coins</translation>
</message>
<message>
- <location line="-29"/>
+ <location line="-28"/>
<source>Don&apos;t generate coins</source>
<translation>Don&apos;t generate coins</translation>
</message>
<message>
- <location line="+75"/>
+ <location line="+74"/>
<source>Specify data directory</source>
<translation>Specify data directory</translation>
</message>
@@ -2251,12 +2359,12 @@ Address: %4
<translation>Maintain at most &lt;n&gt; connections to peers (default: 125)</translation>
</message>
<message>
- <location line="-50"/>
+ <location line="-49"/>
<source>Connect to a node to retrieve peer addresses, and disconnect</source>
<translation>Connect to a node to retrieve peer addresses, and disconnect</translation>
</message>
<message>
- <location line="+81"/>
+ <location line="+80"/>
<source>Specify your own public address</source>
<translation>Specify your own public address</translation>
</message>
@@ -2266,17 +2374,17 @@ Address: %4
<translation>Threshold for disconnecting misbehaving peers (default: 100)</translation>
</message>
<message>
- <location line="-133"/>
+ <location line="-132"/>
<source>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</source>
<translation>Number of seconds to keep misbehaving peers from reconnecting (default: 86400)</translation>
</message>
<message>
- <location line="-29"/>
+ <location line="-32"/>
<source>An error occurred while setting up the RPC port %u for listening on IPv4: %s</source>
<translation>An error occurred while setting up the RPC port %u for listening on IPv4: %s</translation>
</message>
<message>
- <location line="+27"/>
+ <location line="+30"/>
<source>Listen for JSON-RPC connections on &lt;port&gt; (default: 8332 or testnet: 18332)</source>
<translation>Listen for JSON-RPC connections on &lt;port&gt; (default: 8332 or testnet: 18332)</translation>
</message>
@@ -2286,7 +2394,7 @@ Address: %4
<translation>Accept command line and JSON-RPC commands</translation>
</message>
<message>
- <location line="+78"/>
+ <location line="+77"/>
<source>Run in the background as a daemon and accept commands</source>
<translation>Run in the background as a daemon and accept commands</translation>
</message>
@@ -2296,32 +2404,37 @@ Address: %4
<translation>Use the test network</translation>
</message>
<message>
- <location line="-109"/>
+ <location line="-108"/>
<source>Accept connections from outside (default: 1 if no -proxy or -connect)</source>
<translation>Accept connections from outside (default: 1 if no -proxy or -connect)</translation>
</message>
<message>
- <location line="-77"/>
+ <location line="-82"/>
<source>%s, you must set a rpcpassword in the configuration file:
- %s
+%s
It is recommended you use the following random password:
rpcuser=bitcoinrpc
rpcpassword=%s
(you do not need to remember this password)
The username and password MUST NOT be the same.
If the file does not exist, create it with owner-readable-only file permissions.
+It is also recommended to set alertnotify so you are notified of problems;
+for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.com
</source>
<translation>%s, you must set a rpcpassword in the configuration file:
- %s
+%s
It is recommended you use the following random password:
rpcuser=bitcoinrpc
rpcpassword=%s
(you do not need to remember this password)
The username and password MUST NOT be the same.
-If the file does not exist, create it with owner-readable-only file permissions.</translation>
+If the file does not exist, create it with owner-readable-only file permissions.
+It is also recommended to set alertnotify so you are notified of problems;
+for example: alertnotify=echo %%s | mail -s &quot;Bitcoin Alert&quot; admin@foo.com
+</translation>
</message>
<message>
- <location line="+15"/>
+ <location line="+17"/>
<source>An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s</source>
<translation>An error occurred while setting up the RPC port %u for listening on IPv6, falling back to IPv4: %s</translation>
</message>
@@ -2352,6 +2465,11 @@ If the file does not exist, create it with owner-readable-only file permissions.
</message>
<message>
<location line="+3"/>
+ <source>Execute command when a relevant alert is received (%s in cmd is replaced by message)</source>
+ <translation>Execute command when a relevant alert is received (%s in cmd is replaced by message)</translation>
+ </message>
+ <message>
+ <location line="+3"/>
<source>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</source>
<translation>Execute command when a wallet transaction changes (%s in cmd is replaced by TxID)</translation>
</message>
@@ -2526,7 +2644,7 @@ If the file does not exist, create it with owner-readable-only file permissions.
<translation>Find peers using DNS lookup (default: 1 unless -connect)</translation>
</message>
<message>
- <location line="+4"/>
+ <location line="+3"/>
<source>How many blocks to check at startup (default: 288, 0 = all)</source>
<translation>How many blocks to check at startup (default: 288, 0 = all)</translation>
</message>
@@ -2538,7 +2656,7 @@ If the file does not exist, create it with owner-readable-only file permissions.
<message>
<location line="+24"/>
<source>Rebuild block chain index from current blk000??.dat files</source>
- <translation type="unfinished"></translation>
+ <translation>Rebuild block chain index from current blk000??.dat files</translation>
</message>
<message>
<location line="+37"/>
@@ -2696,22 +2814,22 @@ If the file does not exist, create it with owner-readable-only file permissions.
<translation>Password for JSON-RPC connections</translation>
</message>
<message>
- <location line="-69"/>
+ <location line="-68"/>
<source>Allow JSON-RPC connections from specified IP address</source>
<translation>Allow JSON-RPC connections from specified IP address</translation>
</message>
<message>
- <location line="+78"/>
+ <location line="+77"/>
<source>Send commands to node running on &lt;ip&gt; (default: 127.0.0.1)</source>
<translation>Send commands to node running on &lt;ip&gt; (default: 127.0.0.1)</translation>
</message>
<message>
- <location line="-121"/>
+ <location line="-120"/>
<source>Execute command when the best block changes (%s in cmd is replaced by block hash)</source>
<translation>Execute command when the best block changes (%s in cmd is replaced by block hash)</translation>
</message>
<message>
- <location line="+143"/>
+ <location line="+142"/>
<source>Upgrade wallet to latest format</source>
<translation>Upgrade wallet to latest format</translation>
</message>
@@ -2741,12 +2859,12 @@ If the file does not exist, create it with owner-readable-only file permissions.
<translation>Server private key (default: server.pem)</translation>
</message>
<message>
- <location line="-152"/>
+ <location line="-154"/>
<source>Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)</source>
<translation>Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)</translation>
</message>
<message>
- <location line="+164"/>
+ <location line="+166"/>
<source>This help message</source>
<translation>This help message</translation>
</message>
@@ -2756,7 +2874,7 @@ If the file does not exist, create it with owner-readable-only file permissions.
<translation>Unable to bind to %s on this computer (bind returned error %d, %s)</translation>
</message>
<message>
- <location line="-87"/>
+ <location line="-86"/>
<source>Connect through socks proxy</source>
<translation>Connect through socks proxy</translation>
</message>
@@ -2766,12 +2884,12 @@ If the file does not exist, create it with owner-readable-only file permissions.
<translation>Allow DNS lookups for -addnode, -seednode and -connect</translation>
</message>
<message>
- <location line="+58"/>
+ <location line="+57"/>
<source>Loading addresses...</source>
<translation>Loading addresses...</translation>
</message>
<message>
- <location line="-36"/>
+ <location line="-35"/>
<source>Error loading wallet.dat: Wallet corrupted</source>
<translation>Error loading wallet.dat: Wallet corrupted</translation>
</message>
@@ -2781,17 +2899,17 @@ If the file does not exist, create it with owner-readable-only file permissions.
<translation>Error loading wallet.dat: Wallet requires newer version of Bitcoin</translation>
</message>
<message>
- <location line="+88"/>
+ <location line="+87"/>
<source>Wallet needed to be rewritten: restart Bitcoin to complete</source>
<translation>Wallet needed to be rewritten: restart Bitcoin to complete</translation>
</message>
<message>
- <location line="-90"/>
+ <location line="-89"/>
<source>Error loading wallet.dat</source>
<translation>Error loading wallet.dat</translation>
</message>
<message>
- <location line="+31"/>
+ <location line="+30"/>
<source>Invalid -proxy address: &apos;%s&apos;</source>
<translation>Invalid -proxy address: &apos;%s&apos;</translation>
</message>
@@ -2806,7 +2924,7 @@ If the file does not exist, create it with owner-readable-only file permissions.
<translation>Unknown -socks proxy version requested: %i</translation>
</message>
<message>
- <location line="-92"/>
+ <location line="-91"/>
<source>Cannot resolve -bind address: &apos;%s&apos;</source>
<translation>Cannot resolve -bind address: &apos;%s&apos;</translation>
</message>
@@ -2816,17 +2934,17 @@ If the file does not exist, create it with owner-readable-only file permissions.
<translation>Cannot resolve -externalip address: &apos;%s&apos;</translation>
</message>
<message>
- <location line="+46"/>
+ <location line="+45"/>
<source>Invalid amount for -paytxfee=&lt;amount&gt;: &apos;%s&apos;</source>
<translation>Invalid amount for -paytxfee=&lt;amount&gt;: &apos;%s&apos;</translation>
</message>
<message>
- <location line="-25"/>
+ <location line="-24"/>
<source>Error: could not start node</source>
<translation>Error: could not start node</translation>
</message>
<message>
- <location line="+26"/>
+ <location line="+25"/>
<source>Invalid amount</source>
<translation>Invalid amount</translation>
</message>
@@ -2841,7 +2959,7 @@ If the file does not exist, create it with owner-readable-only file permissions.
<translation>Loading block index...</translation>
</message>
<message>
- <location line="-60"/>
+ <location line="-59"/>
<source>Add a node to connect to and attempt to keep the connection open</source>
<translation>Add a node to connect to and attempt to keep the connection open</translation>
</message>
@@ -2851,22 +2969,17 @@ If the file does not exist, create it with owner-readable-only file permissions.
<translation>Unable to bind to %s on this computer. Bitcoin is probably already running.</translation>
</message>
<message>
- <location line="+70"/>
- <source>Find peers using internet relay chat (default: 0)</source>
- <translation>Find peers using internet relay chat (default: 0)</translation>
- </message>
- <message>
- <location line="-2"/>
+ <location line="+68"/>
<source>Fee per KB to add to transactions you send</source>
<translation>Fee per KB to add to transactions you send</translation>
</message>
<message>
- <location line="+18"/>
+ <location line="+17"/>
<source>Loading wallet...</source>
<translation>Loading wallet...</translation>
</message>
<message>
- <location line="-55"/>
+ <location line="-54"/>
<source>Cannot downgrade wallet</source>
<translation>Cannot downgrade wallet</translation>
</message>
@@ -2881,22 +2994,22 @@ If the file does not exist, create it with owner-readable-only file permissions.
<translation>Cannot write default address</translation>
</message>
<message>
- <location line="+65"/>
+ <location line="+64"/>
<source>Rescanning...</source>
<translation>Rescanning...</translation>
</message>
<message>
- <location line="-57"/>
+ <location line="-56"/>
<source>Done loading</source>
<translation>Done loading</translation>
</message>
<message>
- <location line="+80"/>
+ <location line="+79"/>
<source>To use the %s option</source>
<translation>To use the %s option</translation>
</message>
<message>
- <location line="-72"/>
+ <location line="-71"/>
<source>Error</source>
<translation>Error</translation>
</message>
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index cd3170a306..6b1b4e3d8e 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -219,9 +219,8 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
settings.setValue("fMinimizeToTray", fMinimizeToTray);
break;
case MapPortUPnP:
- fUseUPnP = value.toBool();
- settings.setValue("fUseUPnP", fUseUPnP);
- MapPort();
+ settings.setValue("fUseUPnP", value.toBool());
+ MapPort(value.toBool());
break;
case MinimizeOnClose:
fMinimizeOnClose = value.toBool();
diff --git a/src/qt/res/icons/bitcoin.icns b/src/qt/res/icons/bitcoin.icns
index 3c757080aa..54d02d34dd 100644
--- a/src/qt/res/icons/bitcoin.icns
+++ b/src/qt/res/icons/bitcoin.icns
Binary files differ
diff --git a/src/qt/res/icons/bitcoin.svg b/src/qt/res/icons/bitcoin.svg
new file mode 100644
index 0000000000..14cf0c5e11
--- /dev/null
+++ b/src/qt/res/icons/bitcoin.svg
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Designer: Jonas Schnelli
+ License: MIT
+-->
+
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1"
+ id="svg2" sodipodi:docname="bitcoin-logo-noshadow.svg" inkscape:version="0.48.2 r9819" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1024px" height="1024px"
+ viewBox="-34 -34 580 580" enable-background="new 0 0 1024 1024" xml:space="preserve">
+
+ <!-- nice shadow with alpha 0.35 -->
+ <filter id="dropShadowAlpha">
+ <feColorMatrix result="matrixOut" in="SourceAlpha" type="saturate"
+ values="0.1" />
+ <feGaussianBlur in="matrixOut" result="blur-out" stdDeviation="6" />
+ <feColorMatrix in="blur-out" result="color-out" type="matrix"
+ values="0 0 0 0 0
+ 0 0 0 0 0
+ 0 0 0 0 0
+ 0 0 0 0.35 0"/>
+ <feBlend in="SourceGraphic" in2="color-out" mode="normal" />
+ </filter>
+
+ <g>
+ <!-- white background circle for making B not transparent but still keep inner shadows -->
+ <circle cx="255" cy="255" r="200" stroke-width="2" fill="white"/>
+
+ <radialGradient id="innerBtop" cx="277.4905" cy="196.4412" r="34.3969" gradientUnits="userSpaceOnUse">
+ <stop offset="0" style="stop-color:#F9AA4B"/>
+ <stop offset="1" style="stop-color:#F7931A"/>
+ </radialGradient>
+ <path fill="url(#innerBtop)" filter="url(#dropShadowAlpha)" d="M254.647,174.6l-13.983,56.08c15.855,3.951,64.735,20.071,72.656-11.656
+ C321.568,185.928,270.503,178.552,254.647,174.6z"/>
+
+ <radialGradient id="innerBbottom" cx="261.9153" cy="284.5671" r="39.8381" gradientUnits="userSpaceOnUse">
+ <stop offset="0" style="stop-color:#F9AA4B"/>
+ <stop offset="1" style="stop-color:#F7931A"/>
+ </radialGradient>
+ <path fill="url(#innerBbottom)" filter="url(#dropShadowAlpha)" d="M233.608,258.984l-15.425,61.832c19.04,4.729,77.769,23.584,86.448-11.296
+ C313.703,273.144,252.647,263.736,233.608,258.984z"/>
+
+ <radialGradient id="coinShape" cx="256.0276" cy="256.0027" r="255.9878" gradientUnits="userSpaceOnUse">
+ <stop offset="0" style="stop-color:#F9AA4B"/>
+ <stop offset="1" style="stop-color:#F7931A"/>
+ </radialGradient>
+ <path fill="url(#coinShape)" filter="url(#dropShadowAlpha)" d="M317.871,7.656c-137.12-34.192-276.024,49.28-310.2,186.44
+ c-34.208,137.136,49.256,276.048,186.36,310.24c137.16,34.199,276.063-49.265,310.256-186.408
+ C538.479,180.776,455.023,41.848,317.871,7.656z M368.807,219.528c-3.688,24.936-17.512,37.008-35.864,41.24
+ c25.2,13.12,38.024,33.239,25.809,68.12c-15.16,43.319-51.176,46.976-99.072,37.912l-11.624,46.584l-28.088-7l11.472-45.96
+ c-7.279-1.809-14.72-3.729-22.384-5.809l-11.512,46.177l-28.056-7l11.624-46.673c-6.561-1.68-13.225-3.464-20.024-5.168
+ l-36.552-9.111l13.943-32.152c0,0,20.696,5.504,20.416,5.096c7.952,1.969,11.48-3.216,12.872-6.672l18.368-73.64l0.048-0.2
+ l13.104-52.568c0.344-5.968-1.712-13.496-13.088-16.336c0.439-0.296-20.4-5.072-20.4-5.072l7.472-30l38.736,9.673l-0.032,0.144
+ c5.824,1.448,11.824,2.824,17.937,4.216L245.423,89.2l28.072,7l-11.28,45.224c7.536,1.721,15.12,3.456,22.504,5.297l11.2-44.929
+ l28.088,7l-11.504,46.145C347.967,167.152,373.904,185.464,368.807,219.528z"/>
+ </g>
+</svg>
diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp
index 2133a5e729..eb3ce48a6e 100644
--- a/src/qt/sendcoinsdialog.cpp
+++ b/src/qt/sendcoinsdialog.cpp
@@ -202,7 +202,7 @@ SendCoinsEntry *SendCoinsDialog::addEntry()
entry->clear();
entry->setFocus();
ui->scrollAreaWidgetContents->resize(ui->scrollAreaWidgetContents->sizeHint());
- QCoreApplication::instance()->processEvents();
+ qApp->processEvents();
QScrollBar* bar = ui->scrollArea->verticalScrollBar();
if(bar)
bar->setSliderPosition(bar->maximum());
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index 6be34e5ff4..1d02b81fb6 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -10,26 +10,17 @@
#include "addressbookpage.h"
#include "sendcoinsdialog.h"
#include "signverifymessagedialog.h"
-#include "optionsdialog.h"
-#include "aboutdialog.h"
#include "clientmodel.h"
#include "walletmodel.h"
-#include "editaddressdialog.h"
#include "optionsmodel.h"
-#include "transactiondescdialog.h"
-#include "addresstablemodel.h"
#include "transactionview.h"
#include "overviewpage.h"
-#include "bitcoinunits.h"
-#include "guiconstants.h"
#include "askpassphrasedialog.h"
-#include "guiutil.h"
#include "ui_interface.h"
#include <QVBoxLayout>
#include <QActionGroup>
#include <QAction>
-#include <QLabel>
#include <QDesktopServices>
#include <QFileDialog>
@@ -37,13 +28,8 @@ WalletView::WalletView(QWidget *parent, BitcoinGUI *_gui):
QStackedWidget(parent),
gui(_gui),
clientModel(0),
- walletModel(0),
- encryptWalletAction(0),
- changePassphraseAction(0)
+ walletModel(0)
{
- // Create actions for the toolbar, menu bar and tray/dock icon
- createActions();
-
// Create tabs
overviewPage = new OverviewPage();
@@ -88,74 +74,6 @@ WalletView::~WalletView()
{
}
-void WalletView::createActions()
-{
- QActionGroup *tabGroup = new QActionGroup(this);
-
- overviewAction = new QAction(QIcon(":/icons/overview"), tr("&Overview"), this);
- overviewAction->setStatusTip(tr("Show general overview of wallet"));
- overviewAction->setToolTip(overviewAction->statusTip());
- overviewAction->setCheckable(true);
- overviewAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_1));
- tabGroup->addAction(overviewAction);
-
- sendCoinsAction = new QAction(QIcon(":/icons/send"), tr("&Send coins"), this);
- sendCoinsAction->setStatusTip(tr("Send coins to a Bitcoin address"));
- sendCoinsAction->setToolTip(sendCoinsAction->statusTip());
- sendCoinsAction->setCheckable(true);
- sendCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_2));
- tabGroup->addAction(sendCoinsAction);
-
- receiveCoinsAction = new QAction(QIcon(":/icons/receiving_addresses"), tr("&Receive coins"), this);
- receiveCoinsAction->setStatusTip(tr("Show the list of addresses for receiving payments"));
- receiveCoinsAction->setToolTip(receiveCoinsAction->statusTip());
- receiveCoinsAction->setCheckable(true);
- receiveCoinsAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_3));
- tabGroup->addAction(receiveCoinsAction);
-
- historyAction = new QAction(QIcon(":/icons/history"), tr("&Transactions"), this);
- historyAction->setStatusTip(tr("Browse transaction history"));
- historyAction->setToolTip(historyAction->statusTip());
- historyAction->setCheckable(true);
- historyAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_4));
- tabGroup->addAction(historyAction);
-
- addressBookAction = new QAction(QIcon(":/icons/address-book"), tr("&Address Book"), this);
- addressBookAction->setStatusTip(tr("Edit the list of stored addresses and labels"));
- addressBookAction->setToolTip(addressBookAction->statusTip());
- addressBookAction->setCheckable(true);
- addressBookAction->setShortcut(QKeySequence(Qt::ALT + Qt::Key_5));
- tabGroup->addAction(addressBookAction);
-
- connect(overviewAction, SIGNAL(triggered()), this, SLOT(gotoOverviewPage()));
- connect(sendCoinsAction, SIGNAL(triggered()), this, SLOT(gotoSendCoinsPage()));
- connect(receiveCoinsAction, SIGNAL(triggered()), this, SLOT(gotoReceiveCoinsPage()));
- connect(historyAction, SIGNAL(triggered()), this, SLOT(gotoHistoryPage()));
- connect(addressBookAction, SIGNAL(triggered()), this, SLOT(gotoAddressBookPage()));
-
- encryptWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Encrypt Wallet..."), this);
- encryptWalletAction->setStatusTip(tr("Encrypt the private keys that belong to your wallet"));
- encryptWalletAction->setCheckable(true);
- backupWalletAction = new QAction(QIcon(":/icons/filesave"), tr("&Backup Wallet..."), this);
- backupWalletAction->setStatusTip(tr("Backup wallet to another location"));
- changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase..."), this);
- changePassphraseAction->setStatusTip(tr("Change the passphrase used for wallet encryption"));
- signMessageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message..."), this);
- signMessageAction->setStatusTip(tr("Sign messages with your Bitcoin addresses to prove you own them"));
- verifyMessageAction = new QAction(QIcon(":/icons/transaction_0"), tr("&Verify message..."), this);
- verifyMessageAction->setStatusTip(tr("Verify messages to ensure they were signed with specified Bitcoin addresses"));
-
- exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this);
- exportAction->setStatusTip(tr("Export the data in the current tab to a file"));
- exportAction->setToolTip(exportAction->statusTip());
-
- connect(encryptWalletAction, SIGNAL(triggered(bool)), this, SLOT(encryptWallet(bool)));
- connect(backupWalletAction, SIGNAL(triggered()), this, SLOT(backupWallet()));
- connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase()));
- connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab()));
- connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab()));
-}
-
void WalletView::setBitcoinGUI(BitcoinGUI *gui)
{
this->gui = gui;
@@ -164,7 +82,7 @@ void WalletView::setBitcoinGUI(BitcoinGUI *gui)
void WalletView::setClientModel(ClientModel *clientModel)
{
this->clientModel = clientModel;
- if(clientModel)
+ if (clientModel)
{
overviewPage->setClientModel(clientModel);
addressBookPage->setOptionsModel(clientModel->getOptionsModel());
@@ -175,7 +93,7 @@ void WalletView::setClientModel(ClientModel *clientModel)
void WalletView::setWalletModel(WalletModel *walletModel)
{
this->walletModel = walletModel;
- if(walletModel)
+ if (walletModel)
{
// Receive and report messages from wallet thread
connect(walletModel, SIGNAL(message(QString,QString,unsigned int)), gui, SLOT(message(QString,QString,unsigned int)));
@@ -222,52 +140,52 @@ void WalletView::incomingTransaction(const QModelIndex& parent, int start, int /
void WalletView::gotoOverviewPage()
{
- overviewAction->setChecked(true);
+ gui->getOverviewAction()->setChecked(true);
setCurrentWidget(overviewPage);
- exportAction->setEnabled(false);
- disconnect(exportAction, SIGNAL(triggered()), 0, 0);
+ gui->getExportAction()->setEnabled(false);
+ disconnect(gui->getExportAction(), SIGNAL(triggered()), 0, 0);
}
void WalletView::gotoHistoryPage()
{
- historyAction->setChecked(true);
+ gui->getHistoryAction()->setChecked(true);
setCurrentWidget(transactionsPage);
- exportAction->setEnabled(true);
- disconnect(exportAction, SIGNAL(triggered()), 0, 0);
- connect(exportAction, SIGNAL(triggered()), transactionView, SLOT(exportClicked()));
+ gui->getExportAction()->setEnabled(true);
+ disconnect(gui->getExportAction(), SIGNAL(triggered()), 0, 0);
+ connect(gui->getExportAction(), SIGNAL(triggered()), transactionView, SLOT(exportClicked()));
}
void WalletView::gotoAddressBookPage()
{
- addressBookAction->setChecked(true);
+ gui->getAddressBookAction()->setChecked(true);
setCurrentWidget(addressBookPage);
- exportAction->setEnabled(true);
- disconnect(exportAction, SIGNAL(triggered()), 0, 0);
- connect(exportAction, SIGNAL(triggered()), addressBookPage, SLOT(exportClicked()));
+ gui->getExportAction()->setEnabled(true);
+ disconnect(gui->getExportAction(), SIGNAL(triggered()), 0, 0);
+ connect(gui->getExportAction(), SIGNAL(triggered()), addressBookPage, SLOT(exportClicked()));
}
void WalletView::gotoReceiveCoinsPage()
{
- receiveCoinsAction->setChecked(true);
+ gui->getReceiveCoinsAction()->setChecked(true);
setCurrentWidget(receiveCoinsPage);
- exportAction->setEnabled(true);
- disconnect(exportAction, SIGNAL(triggered()), 0, 0);
- connect(exportAction, SIGNAL(triggered()), receiveCoinsPage, SLOT(exportClicked()));
+ gui->getExportAction()->setEnabled(true);
+ disconnect(gui->getExportAction(), SIGNAL(triggered()), 0, 0);
+ connect(gui->getExportAction(), SIGNAL(triggered()), receiveCoinsPage, SLOT(exportClicked()));
}
void WalletView::gotoSendCoinsPage(QString addr)
{
- sendCoinsAction->setChecked(true);
+ gui->getSendCoinsAction()->setChecked(true);
setCurrentWidget(sendCoinsPage);
- exportAction->setEnabled(false);
- disconnect(exportAction, SIGNAL(triggered()), 0, 0);
+ gui->getExportAction()->setEnabled(false);
+ disconnect(gui->getExportAction(), SIGNAL(triggered()), 0, 0);
- if(!addr.isEmpty())
+ if (!addr.isEmpty())
sendCoinsPage->setAddress(addr);
}
@@ -276,7 +194,7 @@ void WalletView::gotoSignMessageTab(QString addr)
// call show() in showTab_SM()
signVerifyMessageDialog->showTab_SM(true);
- if(!addr.isEmpty())
+ if (!addr.isEmpty())
signVerifyMessageDialog->setAddress_SM(addr);
}
@@ -285,7 +203,7 @@ void WalletView::gotoVerifyMessageTab(QString addr)
// call show() in showTab_VM()
signVerifyMessageDialog->showTab_VM(true);
- if(!addr.isEmpty())
+ if (!addr.isEmpty())
signVerifyMessageDialog->setAddress_VM(addr);
}
@@ -327,8 +245,8 @@ void WalletView::backupWallet()
{
QString saveDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
QString filename = QFileDialog::getSaveFileName(this, tr("Backup Wallet"), saveDir, tr("Wallet Data (*.dat)"));
- if(!filename.isEmpty()) {
- if(!walletModel->backupWallet(filename)) {
+ if (!filename.isEmpty()) {
+ if (!walletModel->backupWallet(filename)) {
gui->message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to the new location."),
CClientUIInterface::MSG_ERROR);
}
@@ -350,7 +268,7 @@ void WalletView::unlockWallet()
if(!walletModel)
return;
// Unlock wallet when requested by wallet model
- if(walletModel->getEncryptionStatus() == WalletModel::Locked)
+ if (walletModel->getEncryptionStatus() == WalletModel::Locked)
{
AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, this);
dlg.setModel(walletModel);
diff --git a/src/qt/walletview.h b/src/qt/walletview.h
index caa51d7c3a..6bcd70baf9 100644
--- a/src/qt/walletview.h
+++ b/src/qt/walletview.h
@@ -10,7 +10,6 @@
#include <QStackedWidget>
class BitcoinGUI;
-class TransactionTableModel;
class ClientModel;
class WalletModel;
class TransactionView;
@@ -18,7 +17,6 @@ class OverviewPage;
class AddressBookPage;
class SendCoinsDialog;
class SignVerifyMessageDialog;
-class Notificator;
class RPCConsole;
QT_BEGIN_NAMESPACE
@@ -35,6 +33,7 @@ QT_END_NAMESPACE
class WalletView : public QStackedWidget
{
Q_OBJECT
+
public:
explicit WalletView(QWidget *parent, BitcoinGUI *_gui);
~WalletView();
@@ -66,35 +65,8 @@ private:
SendCoinsDialog *sendCoinsPage;
SignVerifyMessageDialog *signVerifyMessageDialog;
- QLabel *labelEncryptionIcon;
- QLabel *labelConnectionsIcon;
- QLabel *labelBlocksIcon;
- QLabel *progressBarLabel;
-
- QAction *overviewAction;
- QAction *historyAction;
- QAction *quitAction;
- QAction *sendCoinsAction;
- QAction *addressBookAction;
- QAction *signMessageAction;
- QAction *verifyMessageAction;
- QAction *aboutAction;
- QAction *receiveCoinsAction;
- QAction *optionsAction;
- QAction *toggleHideAction;
- QAction *exportAction;
- QAction *encryptWalletAction;
- QAction *backupWalletAction;
- QAction *changePassphraseAction;
- QAction *aboutQtAction;
- QAction *openRPCConsoleAction;
-
TransactionView *transactionView;
- /** Create the main UI actions. */
- void createActions();
- /** Create the menu bar and sub-menus. */
-
public slots:
/** Switch to overview (home) page */
void gotoOverviewPage();
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index 21eb2fd1aa..526a7b5b32 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -1289,7 +1289,7 @@ void ThreadCleanWalletPassphrase(void* parg)
break;
LEAVE_CRITICAL_SECTION(cs_nWalletUnlockTime);
- Sleep(nToSleep);
+ MilliSleep(nToSleep);
ENTER_CRITICAL_SECTION(cs_nWalletUnlockTime);
} while(1);
diff --git a/src/test/bignum_tests.cpp b/src/test/bignum_tests.cpp
index 5b898d1499..196b7274f4 100644
--- a/src/test/bignum_tests.cpp
+++ b/src/test/bignum_tests.cpp
@@ -128,51 +128,51 @@ BOOST_AUTO_TEST_CASE(bignum_SetCompact)
CBigNum num;
num.SetCompact(0);
BOOST_CHECK_EQUAL(num.GetHex(), "0");
- BOOST_CHECK_EQUAL(num.GetCompact(), 0);
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
num.SetCompact(0x00123456);
BOOST_CHECK_EQUAL(num.GetHex(), "0");
- BOOST_CHECK_EQUAL(num.GetCompact(), 0);
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
num.SetCompact(0x01123456);
BOOST_CHECK_EQUAL(num.GetHex(), "12");
- BOOST_CHECK_EQUAL(num.GetCompact(), 0x01120000);
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x01120000U);
// Make sure that we don't generate compacts with the 0x00800000 bit set
num = 0x80;
- BOOST_CHECK_EQUAL(num.GetCompact(), 0x02008000);
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x02008000U);
num.SetCompact(0x01fedcba);
BOOST_CHECK_EQUAL(num.GetHex(), "-7e");
- BOOST_CHECK_EQUAL(num.GetCompact(), 0x01fe0000);
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x01fe0000U);
num.SetCompact(0x02123456);
BOOST_CHECK_EQUAL(num.GetHex(), "1234");
- BOOST_CHECK_EQUAL(num.GetCompact(), 0x02123400);
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x02123400U);
num.SetCompact(0x03123456);
BOOST_CHECK_EQUAL(num.GetHex(), "123456");
- BOOST_CHECK_EQUAL(num.GetCompact(), 0x03123456);
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x03123456U);
num.SetCompact(0x04123456);
BOOST_CHECK_EQUAL(num.GetHex(), "12345600");
- BOOST_CHECK_EQUAL(num.GetCompact(), 0x04123456);
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x04123456U);
num.SetCompact(0x04923456);
BOOST_CHECK_EQUAL(num.GetHex(), "-12345600");
- BOOST_CHECK_EQUAL(num.GetCompact(), 0x04923456);
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x04923456U);
num.SetCompact(0x05009234);
BOOST_CHECK_EQUAL(num.GetHex(), "92340000");
- BOOST_CHECK_EQUAL(num.GetCompact(), 0x05009234);
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x05009234U);
num.SetCompact(0x20123456);
BOOST_CHECK_EQUAL(num.GetHex(), "1234560000000000000000000000000000000000000000000000000000000000");
- BOOST_CHECK_EQUAL(num.GetCompact(), 0x20123456);
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0x20123456U);
num.SetCompact(0xff123456);
BOOST_CHECK_EQUAL(num.GetHex(), "123456000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
- BOOST_CHECK_EQUAL(num.GetCompact(), 0xff123456);
+ BOOST_CHECK_EQUAL(num.GetCompact(), 0xff123456U);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 7297bb9a75..d6f836d367 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -216,7 +216,7 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
CScript s;
s << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
BOOST_CHECK(Solver(s, whichType, solutions));
- BOOST_CHECK_EQUAL(solutions.size(), 4);
+ BOOST_CHECK_EQUAL(solutions.size(), 4U);
CTxDestination addr;
BOOST_CHECK(!ExtractDestination(s, addr));
BOOST_CHECK(IsMine(keystore, s));
@@ -229,7 +229,7 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
CScript s;
s << OP_1 << key[0].GetPubKey() << key[1].GetPubKey() << OP_2 << OP_CHECKMULTISIG;
BOOST_CHECK(Solver(s, whichType, solutions));
- BOOST_CHECK_EQUAL(solutions.size(), 4);
+ BOOST_CHECK_EQUAL(solutions.size(), 4U);
vector<CTxDestination> addrs;
int nRequired;
BOOST_CHECK(ExtractDestinations(s, whichType, addrs, nRequired));
diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp
index b5107193fd..3444726ca0 100644
--- a/src/test/script_P2SH_tests.cpp
+++ b/src/test/script_P2SH_tests.cpp
@@ -303,7 +303,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2));
BOOST_CHECK(txTo.AreInputsStandard(coins));
- BOOST_CHECK_EQUAL(txTo.GetP2SHSigOpCount(coins), 1);
+ BOOST_CHECK_EQUAL(txTo.GetP2SHSigOpCount(coins), 1U);
// Make sure adding crap to the scriptSigs makes them non-standard:
for (int i = 0; i < 3; i++)
@@ -327,7 +327,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
txToNonStd.vin[1].scriptSig << OP_0 << Serialize(oneOfEleven);
BOOST_CHECK(!txToNonStd.AreInputsStandard(coins));
- BOOST_CHECK_EQUAL(txToNonStd.GetP2SHSigOpCount(coins), 11);
+ BOOST_CHECK_EQUAL(txToNonStd.GetP2SHSigOpCount(coins), 11U);
txToNonStd.vin[0].scriptSig.clear();
BOOST_CHECK(!txToNonStd.AreInputsStandard(coins));
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index 90ac89f8c5..19ffdcab66 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -29,13 +29,13 @@ BOOST_AUTO_TEST_CASE(varints)
// decode
for (int i = 0; i < 100000; i++) {
- int j;
+ int j = -1;
ss >> VARINT(j);
BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
}
for (uint64 i = 0; i < 100000000000ULL; i += 999999937) {
- uint64 j;
+ uint64 j = -1;
ss >> VARINT(j);
BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
}
diff --git a/src/test/sigopcount_tests.cpp b/src/test/sigopcount_tests.cpp
index 59673f9b3d..1762680adf 100644
--- a/src/test/sigopcount_tests.cpp
+++ b/src/test/sigopcount_tests.cpp
@@ -21,21 +21,21 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount)
{
// Test CScript::GetSigOpCount()
CScript s1;
- BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 0);
- BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 0);
+ BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 0U);
+ BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 0U);
uint160 dummy;
s1 << OP_1 << dummy << dummy << OP_2 << OP_CHECKMULTISIG;
- BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 2);
+ BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 2U);
s1 << OP_IF << OP_CHECKSIG << OP_ENDIF;
- BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 3);
- BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 21);
+ BOOST_CHECK_EQUAL(s1.GetSigOpCount(true), 3U);
+ BOOST_CHECK_EQUAL(s1.GetSigOpCount(false), 21U);
CScript p2sh;
p2sh.SetDestination(s1.GetID());
CScript scriptSig;
scriptSig << OP_0 << Serialize(s1);
- BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig), 3);
+ BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig), 3U);
std::vector<CKey> keys;
for (int i = 0; i < 3; i++)
@@ -46,15 +46,15 @@ BOOST_AUTO_TEST_CASE(GetSigOpCount)
}
CScript s2;
s2.SetMultisig(1, keys);
- BOOST_CHECK_EQUAL(s2.GetSigOpCount(true), 3);
- BOOST_CHECK_EQUAL(s2.GetSigOpCount(false), 20);
+ BOOST_CHECK_EQUAL(s2.GetSigOpCount(true), 3U);
+ BOOST_CHECK_EQUAL(s2.GetSigOpCount(false), 20U);
p2sh.SetDestination(s2.GetID());
- BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(true), 0);
- BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(false), 0);
+ BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(true), 0U);
+ BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(false), 0U);
CScript scriptSig2;
scriptSig2 << OP_1 << dummy << dummy << Serialize(s2);
- BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig2), 3);
+ BOOST_CHECK_EQUAL(p2sh.GetSigOpCount(scriptSig2), 3U);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp
index 1116507a34..1bf9a28acc 100644
--- a/src/test/test_bitcoin.cpp
+++ b/src/test/test_bitcoin.cpp
@@ -17,6 +17,7 @@ extern void noui_connect();
struct TestingSetup {
CCoinsViewDB *pcoinsdbview;
boost::filesystem::path pathTemp;
+ boost::thread_group threadGroup;
TestingSetup() {
fPrintToDebugger = true; // don't want to write to debug.log file
@@ -35,11 +36,12 @@ struct TestingSetup {
RegisterWallet(pwalletMain);
nScriptCheckThreads = 3;
for (int i=0; i < nScriptCheckThreads-1; i++)
- NewThread(ThreadScriptCheck, NULL);
+ threadGroup.create_thread(&ThreadScriptCheck);
}
~TestingSetup()
{
- ThreadScriptCheckQuit();
+ threadGroup.interrupt_all();
+ threadGroup.join_all();
delete pwalletMain;
pwalletMain = NULL;
delete pcoinsTip;
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp
index 1b0ccad511..2d05794cc7 100644
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -323,4 +323,62 @@ BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
}
}
+static int nCounter = 0;
+
+static void Count()
+{
+ ++nCounter;
+ MilliSleep(10);
+}
+
+static void CountWithArg(int arg)
+{
+ nCounter += arg;
+ MilliSleep(10);
+}
+
+BOOST_AUTO_TEST_CASE(util_loop_forever1)
+{
+ boost::thread_group threadGroup;
+
+ threadGroup.create_thread(boost::bind(&LoopForever<void (*)()>, "count", &Count, 1));
+ MilliSleep(1);
+ threadGroup.interrupt_all();
+ BOOST_CHECK_EQUAL(nCounter, 1);
+ nCounter = 0;
+}
+
+BOOST_AUTO_TEST_CASE(util_loop_forever2)
+{
+ boost::thread_group threadGroup;
+
+ boost::function<void()> f = boost::bind(&CountWithArg, 11);
+ threadGroup.create_thread(boost::bind(&LoopForever<boost::function<void()> >, "count11", f, 11));
+ MilliSleep(1);
+ threadGroup.interrupt_all();
+ BOOST_CHECK_EQUAL(nCounter, 11);
+ nCounter = 0;
+}
+
+BOOST_AUTO_TEST_CASE(util_threadtrace1)
+{
+ boost::thread_group threadGroup;
+
+ threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "count11", &Count));
+ threadGroup.join_all();
+ BOOST_CHECK_EQUAL(nCounter, 1);
+ nCounter = 0;
+}
+
+BOOST_AUTO_TEST_CASE(util_threadtrace2)
+{
+ boost::thread_group threadGroup;
+
+ boost::function<void()> f = boost::bind(&CountWithArg, 11);
+ threadGroup.create_thread(boost::bind(&TraceThread<boost::function<void()> >, "count11", f));
+ threadGroup.join_all();
+ BOOST_CHECK_EQUAL(nCounter, 11);
+ nCounter = 0;
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp
index b0b3c47967..a4cbfaee41 100644
--- a/src/test/wallet_tests.cpp
+++ b/src/test/wallet_tests.cpp
@@ -104,22 +104,22 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
// try making 34 cents from 1,2,5,10,20 - we can't do it exactly
BOOST_CHECK( wallet.SelectCoinsMinConf(34 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_GT(nValueRet, 34 * CENT); // but should get more than 34 cents
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 3); // the best should be 20+10+5. it's incredibly unlikely the 1 or 2 got included (but possible)
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 3U); // the best should be 20+10+5. it's incredibly unlikely the 1 or 2 got included (but possible)
// when we try making 7 cents, the smaller coins (1,2,5) are enough. We should see just 2+5
BOOST_CHECK( wallet.SelectCoinsMinConf( 7 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 7 * CENT);
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 2);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U);
// when we try making 8 cents, the smaller coins (1,2,5) are exactly enough.
BOOST_CHECK( wallet.SelectCoinsMinConf( 8 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK(nValueRet == 8 * CENT);
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 3);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 3U);
// when we try making 9 cents, no subset of smaller coins is enough, and we get the next bigger coin (10)
BOOST_CHECK( wallet.SelectCoinsMinConf( 9 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 10 * CENT);
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U);
// now clear out the wallet and start again to test choosing between subsets of smaller coins and the next biggest coin
empty_wallet();
@@ -137,26 +137,26 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
// now try making 16 cents. the best smaller coins can do is 6+7+8 = 21; not as good at the next biggest coin, 20
BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 20 * CENT); // we should get 20 in one coin
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U);
add_coin( 5*CENT); // now we have 5+6+7+8+20+30 = 75 cents total
// now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, better than the next biggest coin, 20
BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 18 * CENT); // we should get 18 in 3 coins
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 3);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 3U);
add_coin( 18*CENT); // now we have 5+6+7+8+18+20+30
// and now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, the same as the next biggest coin, 18
BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 18 * CENT); // we should get 18 in 1 coin
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 1); // because in the event of a tie, the biggest coin wins
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U); // because in the event of a tie, the biggest coin wins
// now try making 11 cents. we should get 5+6
BOOST_CHECK( wallet.SelectCoinsMinConf(11 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 11 * CENT);
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 2);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U);
// check that the smallest bigger coin is used
add_coin( 1*COIN);
@@ -165,11 +165,11 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
add_coin( 4*COIN); // now we have 5+6+7+8+18+20+30+100+200+300+400 = 1094 cents
BOOST_CHECK( wallet.SelectCoinsMinConf(95 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1 * COIN); // we should get 1 BTC in 1 coin
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U);
BOOST_CHECK( wallet.SelectCoinsMinConf(195 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 2 * COIN); // we should get 2 BTC in 1 coin
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U);
// empty the wallet and start again, now with fractions of a cent, to test sub-cent change avoidance
empty_wallet();
@@ -207,7 +207,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
BOOST_CHECK( wallet.SelectCoinsMinConf(500000 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 500000 * COIN); // we should get the exact amount
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 10); // in ten coins
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 10U); // in ten coins
// if there's not enough in the smaller coins to make at least 1 cent change (0.5+0.6+0.7 < 1.0+1.0),
// we need to try finding an exact subset anyway
@@ -220,7 +220,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
add_coin(1111 * CENT);
BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1111 * CENT); // we get the bigger coin
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 1U);
// but sometimes it's possible, and we use an exact subset (0.4 + 0.6 = 1.0)
empty_wallet();
@@ -230,7 +230,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
add_coin(1111 * CENT);
BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 2); // in two coins 0.4+0.6
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U); // in two coins 0.4+0.6
// test avoiding sub-cent change
empty_wallet();
@@ -241,12 +241,12 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
// trying to make 1.0001 from these three coins
BOOST_CHECK( wallet.SelectCoinsMinConf(1.0001 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1.0105 * COIN); // we should get all coins
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 3);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 3U);
// but if we try to make 0.999, we should take the bigger of the two small coins to avoid sub-cent change
BOOST_CHECK( wallet.SelectCoinsMinConf(0.999 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1.01 * COIN); // we should get 1 + 0.01
- BOOST_CHECK_EQUAL(setCoinsRet.size(), 2);
+ BOOST_CHECK_EQUAL(setCoinsRet.size(), 2U);
// test randomness
{
diff --git a/src/txdb.cpp b/src/txdb.cpp
index ae7aceb7f1..5b0527c76c 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/ui_interface.h b/src/ui_interface.h
index f7dbe20894..5b0555c10d 100644
--- a/src/ui_interface.h
+++ b/src/ui_interface.h
@@ -79,9 +79,6 @@ public:
/** Progress message during initialization. */
boost::signals2::signal<void (const std::string &message)> InitMessage;
- /** Initiate client shutdown. */
- boost::signals2::signal<void ()> QueueShutdown;
-
/** Translate a message to the native language of the user. */
boost::signals2::signal<std::string (const char* psz)> Translate;
diff --git a/src/util.cpp b/src/util.cpp
index fc3e846a6b..9f5e08a148 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;
@@ -1431,9 +1429,12 @@ void RenameThread(const char* name)
// removed.
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)
-// pthread_setname_np(name);
+#elif defined(MAC_OSX) && defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
+
+// pthread_setname_np is XCode 10.6-and-later
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
+ pthread_setname_np(name);
+#endif
#else
// Prevent warnings for unused parameters...
diff --git a/src/util.h b/src/util.h
index d129d13692..4d7c81be0b 100644
--- a/src/util.h
+++ b/src/util.h
@@ -15,6 +15,8 @@
typedef int pid_t; /* define for Windows compatibility */
#endif
#include <map>
+#include <list>
+#include <utility>
#include <vector>
#include <string>
@@ -98,13 +100,16 @@ T* alignup(T* p)
#endif
#else
#define MAX_PATH 1024
-inline void Sleep(int64 n)
+#endif
+
+inline void MilliSleep(int64 n)
{
- /*Boost has a year 2038 problem— if the request sleep time is past epoch+2^31 seconds the sleep returns instantly.
- So we clamp our sleeps here to 10 years and hope that boost is fixed by 2028.*/
- boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(n>315576000000LL?315576000000LL:n));
-}
+#if BOOST_VERSION >= 105000
+ boost::this_thread::sleep_for(boost::chrono::milliseconds(n));
+#else
+ boost::this_thread::sleep(boost::posix_time::milliseconds(n));
#endif
+}
/* This GNU C extension enables the compiler to check the format string against the parameters provided.
* X is the number of the "format string" parameter, and Y is the number of the first variadic parameter.
@@ -129,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;
@@ -522,5 +525,60 @@ inline uint32_t ByteReverse(uint32_t value)
return (value<<16) | (value>>16);
}
-#endif
+// Standard wrapper for do-something-forever thread functions.
+// "Forever" really means until the thread is interrupted.
+// Use it like:
+// new boost::thread(boost::bind(&LoopForever<void (*)()>, "dumpaddr", &DumpAddresses, 10000));
+// or maybe:
+// boost::function<void()> f = boost::bind(&FunctionWithArg, argument);
+// threadGroup.create_thread(boost::bind(&LoopForever<boost::function<void()> >, "nothing", f, milliseconds));
+template <typename Callable> void LoopForever(const char* name, Callable func, int64 msecs)
+{
+ std::string s = strprintf("bitcoin-%s", name);
+ RenameThread(s.c_str());
+ printf("%s thread start\n", name);
+ try
+ {
+ while (1)
+ {
+ func();
+ MilliSleep(msecs);
+ }
+ }
+ catch (boost::thread_interrupted)
+ {
+ printf("%s thread stop\n", name);
+ throw;
+ }
+ catch (std::exception& e) {
+ PrintException(&e, name);
+ }
+ catch (...) {
+ PrintException(NULL, name);
+ }
+}
+// .. and a wrapper that just calls func once
+template <typename Callable> void TraceThread(const char* name, Callable func)
+{
+ std::string s = strprintf("bitcoin-%s", name);
+ RenameThread(s.c_str());
+ try
+ {
+ printf("%s thread start\n", name);
+ func();
+ printf("%s thread exit\n", name);
+ }
+ catch (boost::thread_interrupted)
+ {
+ printf("%s thread interrupt\n", name);
+ throw;
+ }
+ catch (std::exception& e) {
+ PrintException(&e, name);
+ }
+ catch (...) {
+ PrintException(NULL, name);
+ }
+}
+#endif
diff --git a/src/wallet.cpp b/src/wallet.cpp
index eecb7d2d22..5761b008f3 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 ecfdafe2eb..e750bfd89e 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 fe9bce21e8..abaf5a0fd1 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,9 +499,9 @@ void ThreadFlushWalletDB(void* parg)
unsigned int nLastSeen = nWalletDBUpdated;
unsigned int nLastFlushed = nWalletDBUpdated;
int64 nLastWalletUpdate = GetTime();
- while (!fShutdown)
+ while (true)
{
- Sleep(500);
+ MilliSleep(500);
if (nLastSeen != nWalletDBUpdated)
{
@@ -522,8 +523,9 @@ void ThreadFlushWalletDB(void* parg)
mi++;
}
- if (nRefCount == 0 && !fShutdown)
+ if (nRefCount == 0)
{
+ boost::this_thread::interruption_point();
map<string, int>::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);
@@ -579,7 +581,7 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
}
}
}
- Sleep(100);
+ MilliSleep(100);
}
return false;
}