boost: drop boost threads for upnp

This commit is contained in:
Cory Fields 2018-02-07 17:20:16 -05:00
parent 0277173b1d
commit f26866b9ca
4 changed files with 61 additions and 43 deletions

View file

@ -165,6 +165,7 @@ void Interrupt()
InterruptRPC(); InterruptRPC();
InterruptREST(); InterruptREST();
InterruptTorControl(); InterruptTorControl();
InterruptMapPort();
if (g_connman) if (g_connman)
g_connman->Interrupt(); g_connman->Interrupt();
} }
@ -191,7 +192,7 @@ void Shutdown()
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
FlushWallets(); FlushWallets();
#endif #endif
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.
@ -1669,7 +1670,9 @@ bool AppInitMain()
Discover(threadGroup); Discover(threadGroup);
// 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

@ -1459,6 +1459,8 @@ void CConnman::WakeMessageHandler()
#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());
@ -1509,35 +1511,29 @@ void ThreadMapPort()
std::string strDesc = "Bitcoin " + FormatFullVersion(); std::string strDesc = "Bitcoin " + 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;
@ -1546,27 +1542,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.
} }

View file

@ -442,7 +442,9 @@ private:
}; };
extern std::unique_ptr<CConnman> g_connman; extern std::unique_ptr<CConnman> g_connman;
void Discover(boost::thread_group& threadGroup); void Discover(boost::thread_group& threadGroup);
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

@ -315,7 +315,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();