Backport 12381 (#3528)

* Merge #12381: Remove more boost threads

004f999 boost: drop boost threads for [alert|block|wallet]notify (Cory Fields)
0827267 boost: drop boost threads from torcontrol (Cory Fields)
ba91724 boost: remove useless threadGroup parameter from Discover (Cory Fields)
f26866b boost: drop boost threads for upnp (Cory Fields)

Pull request description:

  This doesn't completely get rid of boost::thread, but this batch should be easy to review, and leaves us with only threadGroup (scheduler + scriptcheck) remaining.

  Note to reviewers: The upnp diff changes a bunch of whitespace, it's much more clear with 'git diff -w'

Tree-SHA512: 5a356798d0785f93ed143d1f0afafe890bc82f0d470bc969473da2d2aa78bcb9b096f7ba11b92564d546fb447d4bd0d347e7842994ea0170aafd53fda7e0a66e

* fix using std::thread

Signed-off-by: pasta <pasta@dashboost.org>

* Switch to std::thread in NotifyTransactionLock

* Move StopTorControl call from Shutdown to PrepareShutdown

Co-authored-by: Wladimir J. van der Laan <laanwj@gmail.com>
Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
This commit is contained in:
PastaPastaPasta 2020-06-13 18:21:30 +00:00 committed by GitHub
parent de43cf09ff
commit 224d0a3fb2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 81 additions and 69 deletions

View File

@ -220,6 +220,7 @@ void Interrupt()
InterruptREST(); InterruptREST();
InterruptTorControl(); InterruptTorControl();
llmq::InterruptLLMQSystem(); llmq::InterruptLLMQSystem();
InterruptMapPort();
if (g_connman) if (g_connman)
g_connman->Interrupt(); g_connman->Interrupt();
} }
@ -251,7 +252,7 @@ void PrepareShutdown()
bool fRPCInWarmup = RPCIsInWarmup(&statusmessage); bool fRPCInWarmup = RPCIsInWarmup(&statusmessage);
g_wallet_init_interface->Flush(); g_wallet_init_interface->Flush();
MapPort(false); StopMapPort();
// Because these depend on each-other, we make sure that neither can be // Because these depend on each-other, we make sure that neither can be
// using the other before destroying them. // using the other before destroying them.
@ -259,6 +260,8 @@ void PrepareShutdown()
if (g_connman) g_connman->Stop(); if (g_connman) g_connman->Stop();
// if (g_txindex) g_txindex->Stop(); //TODO watch out when backporting bitcoin#13033 (don't accidently put the reset here, as we've already backported bitcoin#13894) // if (g_txindex) g_txindex->Stop(); //TODO watch out when backporting bitcoin#13033 (don't accidently put the reset here, as we've already backported bitcoin#13894)
StopTorControl();
// After everything has been shut down, but before things get flushed, stop the // After everything has been shut down, but before things get flushed, stop the
// CScheduler/checkqueue threadGroup // CScheduler/checkqueue threadGroup
threadGroup.interrupt_all(); threadGroup.interrupt_all();
@ -378,8 +381,7 @@ void Shutdown()
if(!fRequestRestart) { if(!fRequestRestart) {
PrepareShutdown(); PrepareShutdown();
} }
// Shutdown part 2: Stop TOR thread and delete wallet instance // Shutdown part 2: delete wallet instance
StopTorControl();
g_wallet_init_interface->Close(); g_wallet_init_interface->Close();
globalVerifyHandle.reset(); globalVerifyHandle.reset();
ECC_Stop(); ECC_Stop();
@ -695,7 +697,8 @@ static void BlockNotifyCallback(bool initialSync, const CBlockIndex *pBlockIndex
std::string strCmd = gArgs.GetArg("-blocknotify", ""); std::string strCmd = gArgs.GetArg("-blocknotify", "");
if (!strCmd.empty()) { if (!strCmd.empty()) {
boost::replace_all(strCmd, "%s", pBlockIndex->GetBlockHash().GetHex()); boost::replace_all(strCmd, "%s", pBlockIndex->GetBlockHash().GetHex());
boost::thread t(runCommand, strCmd); // thread runs free std::thread t(runCommand, strCmd);
t.detach(); // thread runs free
} }
} }
@ -2221,12 +2224,14 @@ bool AppInitMain()
} }
LogPrintf("chainActive.Height() = %d\n", chain_active_height); LogPrintf("chainActive.Height() = %d\n", chain_active_height);
if (gArgs.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) if (gArgs.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION))
StartTorControl(threadGroup, scheduler); StartTorControl();
Discover(threadGroup); Discover();
// Map ports with UPnP // Map ports with UPnP
MapPort(gArgs.GetBoolArg("-upnp", DEFAULT_UPNP)); if (gArgs.GetBoolArg("-upnp", DEFAULT_UPNP)) {
StartMapPort();
}
CConnman::Options connOptions; CConnman::Options connOptions;
connOptions.nLocalServices = nLocalServices; connOptions.nLocalServices = nLocalServices;

View File

@ -1948,6 +1948,8 @@ void CConnman::WakeSelect()
#ifdef USE_UPNP #ifdef USE_UPNP
static CThreadInterrupt g_upnp_interrupt;
static std::thread g_upnp_thread;
void ThreadMapPort() void ThreadMapPort()
{ {
std::string port = strprintf("%u", GetListenPort()); std::string port = strprintf("%u", GetListenPort());
@ -1998,35 +2000,29 @@ void ThreadMapPort()
std::string strDesc = "Dash Core " + FormatFullVersion(); std::string strDesc = "Dash Core " + FormatFullVersion();
try { do {
while (true) {
#ifndef UPNPDISCOVER_SUCCESS #ifndef UPNPDISCOVER_SUCCESS
/* miniupnpc 1.5 */ /* miniupnpc 1.5 */
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0); port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
#else #else
/* miniupnpc 1.6 */ /* miniupnpc 1.6 */
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0"); port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
#endif #endif
if(r!=UPNPCOMMAND_SUCCESS) if(r!=UPNPCOMMAND_SUCCESS)
LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
port, port, lanaddr, r, strupnperror(r)); port, port, lanaddr, r, strupnperror(r));
else else
LogPrintf("UPnP Port Mapping successful.\n"); LogPrintf("UPnP Port Mapping successful.\n");
}
while(g_upnp_interrupt.sleep_for(std::chrono::minutes(20)));
MilliSleep(20*60*1000); // Refresh every 20 minutes r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
} LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r);
} freeUPNPDevlist(devlist); devlist = nullptr;
catch (const boost::thread_interrupted&) FreeUPNPUrls(&urls);
{
r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r);
freeUPNPDevlist(devlist); devlist = nullptr;
FreeUPNPUrls(&urls);
throw;
}
} else { } else {
LogPrintf("No valid UPnP IGDs found\n"); LogPrintf("No valid UPnP IGDs found\n");
freeUPNPDevlist(devlist); devlist = nullptr; freeUPNPDevlist(devlist); devlist = nullptr;
@ -2035,27 +2031,39 @@ void ThreadMapPort()
} }
} }
void MapPort(bool fUseUPnP) void StartMapPort()
{ {
static std::unique_ptr<boost::thread> upnp_thread; if (!g_upnp_thread.joinable()) {
assert(!g_upnp_interrupt);
if (fUseUPnP) g_upnp_thread = std::thread((std::bind(&TraceThread<void (*)()>, "upnp", &ThreadMapPort)));
{
if (upnp_thread) {
upnp_thread->interrupt();
upnp_thread->join();
}
upnp_thread.reset(new boost::thread(boost::bind(&TraceThread<void (*)()>, "upnp", &ThreadMapPort)));
} }
else if (upnp_thread) { }
upnp_thread->interrupt();
upnp_thread->join(); void InterruptMapPort()
upnp_thread.reset(); {
if(g_upnp_thread.joinable()) {
g_upnp_interrupt();
}
}
void StopMapPort()
{
if(g_upnp_thread.joinable()) {
g_upnp_thread.join();
g_upnp_interrupt.reset();
} }
} }
#else #else
void MapPort(bool) void StartMapPort()
{
// Intentionally left blank.
}
void InterruptMapPort()
{
// Intentionally left blank.
}
void StopMapPort()
{ {
// Intentionally left blank. // Intentionally left blank.
} }
@ -2827,7 +2835,7 @@ bool CConnman::BindListenPort(const CService &addrBind, std::string& strError, b
return true; return true;
} }
void Discover(boost::thread_group& threadGroup) void Discover()
{ {
if (!fDiscover) if (!fDiscover)
return; return;

View File

@ -46,10 +46,6 @@
class CScheduler; class CScheduler;
class CNode; class CNode;
namespace boost {
class thread_group;
} // namespace boost
/** Time between pings automatically sent out for latency probing and keepalive (in seconds). */ /** Time between pings automatically sent out for latency probing and keepalive (in seconds). */
static const int PING_INTERVAL = 2 * 60; static const int PING_INTERVAL = 2 * 60;
/** Time after which to disconnect, after waiting for a ping response (or inactivity). */ /** Time after which to disconnect, after waiting for a ping response (or inactivity). */
@ -651,8 +647,10 @@ private:
friend struct CConnmanTest; friend struct CConnmanTest;
}; };
extern std::unique_ptr<CConnman> g_connman; extern std::unique_ptr<CConnman> g_connman;
void Discover(boost::thread_group& threadGroup); void Discover();
void MapPort(bool fUseUPnP); void StartMapPort();
void InterruptMapPort();
void StopMapPort();
unsigned short GetListenPort(); unsigned short GetListenPort();
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false);

View File

@ -379,7 +379,12 @@ bool OptionsModel::setData(const QModelIndex & index, const QVariant & value, in
break; break;
case MapPortUPnP: // core option - can be changed on-the-fly case MapPortUPnP: // core option - can be changed on-the-fly
settings.setValue("fUseUPnP", value.toBool()); settings.setValue("fUseUPnP", value.toBool());
MapPort(value.toBool()); if (value.toBool()) {
StartMapPort();
} else {
InterruptMapPort();
StopMapPort();
}
break; break;
case MinimizeOnClose: case MinimizeOnClose:
fMinimizeOnClose = value.toBool(); fMinimizeOnClose = value.toBool();

View File

@ -731,7 +731,7 @@ void TorController::reconnect_cb(evutil_socket_t fd, short what, void *arg)
/****** Thread ********/ /****** Thread ********/
static struct event_base *gBase; static struct event_base *gBase;
static boost::thread torControlThread; static std::thread torControlThread;
static void TorControlThread() static void TorControlThread()
{ {
@ -740,7 +740,7 @@ static void TorControlThread()
event_base_dispatch(gBase); event_base_dispatch(gBase);
} }
void StartTorControl(boost::thread_group& threadGroup, CScheduler& scheduler) void StartTorControl()
{ {
assert(!gBase); assert(!gBase);
#ifdef WIN32 #ifdef WIN32
@ -754,7 +754,7 @@ void StartTorControl(boost::thread_group& threadGroup, CScheduler& scheduler)
return; return;
} }
torControlThread = boost::thread(boost::bind(&TraceThread<void (*)()>, "torcontrol", &TorControlThread)); torControlThread = std::thread(std::bind(&TraceThread<void (*)()>, "torcontrol", &TorControlThread));
} }
void InterruptTorControl() void InterruptTorControl()
@ -767,14 +767,8 @@ void InterruptTorControl()
void StopTorControl() void StopTorControl()
{ {
// timed_join() avoids the wallet not closing during a repair-restart. For a 'normal' wallet exit
// it behaves for our cases exactly like the normal join()
if (gBase) { if (gBase) {
#if BOOST_VERSION >= 105000 torControlThread.join();
torControlThread.try_join_for(boost::chrono::seconds(1));
#else
torControlThread.timed_join(boost::posix_time::seconds(1));
#endif
event_base_free(gBase); event_base_free(gBase);
gBase = nullptr; gBase = nullptr;
} }

View File

@ -13,7 +13,7 @@
extern const std::string DEFAULT_TOR_CONTROL; extern const std::string DEFAULT_TOR_CONTROL;
static const bool DEFAULT_LISTEN_ONION = true; static const bool DEFAULT_LISTEN_ONION = true;
void StartTorControl(boost::thread_group& threadGroup, CScheduler& scheduler); void StartTorControl();
void InterruptTorControl(); void InterruptTorControl();
void StopTorControl(); void StopTorControl();

View File

@ -1214,7 +1214,8 @@ static void AlertNotify(const std::string& strMessage)
safeStatus = singleQuote+safeStatus+singleQuote; safeStatus = singleQuote+safeStatus+singleQuote;
boost::replace_all(strCmd, "%s", safeStatus); boost::replace_all(strCmd, "%s", safeStatus);
boost::thread t(runCommand, strCmd); // thread runs free std::thread t(runCommand, strCmd);
t.detach(); // thread runs free
} }
static void CheckForkWarningConditions() static void CheckForkWarningConditions()

View File

@ -45,7 +45,6 @@
#include <future> #include <future>
#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/replace.hpp>
#include <boost/thread.hpp>
static CCriticalSection cs_wallets; static CCriticalSection cs_wallets;
static std::vector<CWallet*> vpwallets GUARDED_BY(cs_wallets); static std::vector<CWallet*> vpwallets GUARDED_BY(cs_wallets);
@ -1169,7 +1168,8 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
if (!strCmd.empty()) if (!strCmd.empty())
{ {
boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex()); boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
boost::thread t(runCommand, strCmd); // thread runs free std::thread t(runCommand, strCmd);
t.detach(); // thread runs free
} }
fAnonymizableTallyCached = false; fAnonymizableTallyCached = false;
@ -5439,7 +5439,8 @@ void CWallet::NotifyTransactionLock(const CTransaction &tx, const llmq::CInstant
std::string strCmd = gArgs.GetArg("-instantsendnotify", ""); std::string strCmd = gArgs.GetArg("-instantsendnotify", "");
if (!strCmd.empty()) { if (!strCmd.empty()) {
boost::replace_all(strCmd, "%s", txHash.GetHex()); boost::replace_all(strCmd, "%s", txHash.GetHex());
boost::thread t(runCommand, strCmd); // thread runs free std::thread t(runCommand, strCmd);
t.detach(); // thread runs free
} }
} }
} }