aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2016-01-08 17:34:41 +0100
committerWladimir J. van der Laan <laanwj@gmail.com>2016-01-08 17:34:51 +0100
commit3b57e9cff09c528201246dbc7b890c1593e49fb1 (patch)
tree02d35c01a5d68c8aa54662cbf0f0acec0681f1f2
parentb1cf0058d9b3d3e218f1dc31ee688e5beb21f573 (diff)
parent8a7f0001be88122256b1a8dc29b066210dc85625 (diff)
downloadbitcoin-3b57e9cff09c528201246dbc7b890c1593e49fb1.tar.xz
Merge pull request #7317
8a7f000 [RPC] remove the option of having multiple timer interfaces (Jonas Schnelli) db198d5 Fix RPCTimerInterface ordering issue Dispatching a QThread from a non Qt thread is not allowed. Always use the HTTPRPCTimerInterface (non QT) to dispatch RPCRunLater threads. (Jonas Schnelli)
-rw-r--r--src/httprpc.cpp4
-rw-r--r--src/qt/rpcconsole.cpp6
-rw-r--r--src/rpcserver.cpp22
-rw-r--r--src/rpcserver.h10
4 files changed, 25 insertions, 17 deletions
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index 2920aa26f7..1466dc0cbf 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -226,7 +226,7 @@ bool StartHTTPRPC()
assert(EventBase());
httpRPCTimerInterface = new HTTPRPCTimerInterface(EventBase());
- RPCRegisterTimerInterface(httpRPCTimerInterface);
+ RPCSetTimerInterface(httpRPCTimerInterface);
return true;
}
@@ -240,7 +240,7 @@ void StopHTTPRPC()
LogPrint("rpc", "Stopping HTTP RPC server\n");
UnregisterHTTPHandler("/", true);
if (httpRPCTimerInterface) {
- RPCUnregisterTimerInterface(httpRPCTimerInterface);
+ RPCUnsetTimerInterface(httpRPCTimerInterface);
delete httpRPCTimerInterface;
httpRPCTimerInterface = 0;
}
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index 4c869b9ac5..7178bc00e6 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -278,7 +278,9 @@ RPCConsole::RPCConsole(const PlatformStyle *platformStyle, QWidget *parent) :
#endif
// Register RPC timer interface
rpcTimerInterface = new QtRPCTimerInterface();
- RPCRegisterTimerInterface(rpcTimerInterface);
+ // avoid accidentally overwriting an existing, non QTThread
+ // based timer interface
+ RPCSetTimerInterfaceIfUnset(rpcTimerInterface);
startExecutor();
setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS);
@@ -293,7 +295,7 @@ RPCConsole::~RPCConsole()
{
GUIUtil::saveWindowGeometry("nRPCConsoleWindow", this);
Q_EMIT stopExecutor();
- RPCUnregisterTimerInterface(rpcTimerInterface);
+ RPCUnsetTimerInterface(rpcTimerInterface);
delete rpcTimerInterface;
delete ui;
}
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index bc419d14d9..78d6898bc3 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -33,7 +33,7 @@ static bool fRPCInWarmup = true;
static std::string rpcWarmupStatus("RPC server started");
static CCriticalSection cs_rpcWarmup;
/* Timer-creating functions */
-static std::vector<RPCTimerInterface*> timerInterfaces;
+static RPCTimerInterface* timerInterface = NULL;
/* Map of name to timer.
* @note Can be changed to std::unique_ptr when C++11 */
static std::map<std::string, boost::shared_ptr<RPCTimerBase> > deadlineTimers;
@@ -546,24 +546,28 @@ std::string HelpExampleRpc(const std::string& methodname, const std::string& arg
"\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
}
-void RPCRegisterTimerInterface(RPCTimerInterface *iface)
+void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
{
- timerInterfaces.push_back(iface);
+ if (!timerInterface)
+ timerInterface = iface;
}
-void RPCUnregisterTimerInterface(RPCTimerInterface *iface)
+void RPCSetTimerInterface(RPCTimerInterface *iface)
{
- std::vector<RPCTimerInterface*>::iterator i = std::find(timerInterfaces.begin(), timerInterfaces.end(), iface);
- assert(i != timerInterfaces.end());
- timerInterfaces.erase(i);
+ timerInterface = iface;
+}
+
+void RPCUnsetTimerInterface(RPCTimerInterface *iface)
+{
+ if (timerInterface == iface)
+ timerInterface = NULL;
}
void RPCRunLater(const std::string& name, boost::function<void(void)> func, int64_t nSeconds)
{
- if (timerInterfaces.empty())
+ if (!timerInterface)
throw JSONRPCError(RPC_INTERNAL_ERROR, "No timer handler registered for RPC");
deadlineTimers.erase(name);
- RPCTimerInterface* timerInterface = timerInterfaces[0];
LogPrint("rpc", "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name());
deadlineTimers.insert(std::make_pair(name, boost::shared_ptr<RPCTimerBase>(timerInterface->NewTimer(func, nSeconds*1000))));
}
diff --git a/src/rpcserver.h b/src/rpcserver.h
index f85ab42f02..9dce318872 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -100,10 +100,12 @@ public:
virtual RPCTimerBase* NewTimer(boost::function<void(void)>& func, int64_t millis) = 0;
};
-/** Register factory function for timers */
-void RPCRegisterTimerInterface(RPCTimerInterface *iface);
-/** Unregister factory function for timers */
-void RPCUnregisterTimerInterface(RPCTimerInterface *iface);
+/** Set the factory function for timers */
+void RPCSetTimerInterface(RPCTimerInterface *iface);
+/** Set the factory function for timer, but only, if unset */
+void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface);
+/** Unset factory function for timers */
+void RPCUnsetTimerInterface(RPCTimerInterface *iface);
/**
* Run func nSeconds from now.