Fix race condition between starting HTTP server thread and setting EventBase()
Split StartHTTPServer into InitHTTPServer and StartHTTPServer to give clients a window to register their handlers without race conditions. Thanks @ajweiss for figuring this out.
This commit is contained in:
parent
6d2bc22146
commit
3a174cd400
3 changed files with 26 additions and 11 deletions
|
@ -320,7 +320,7 @@ static void HTTPWorkQueueRun(WorkQueue<HTTPClosure>* queue)
|
||||||
queue->Run();
|
queue->Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StartHTTPServer(boost::thread_group& threadGroup)
|
bool InitHTTPServer()
|
||||||
{
|
{
|
||||||
struct evhttp* http = 0;
|
struct evhttp* http = 0;
|
||||||
struct event_base* base = 0;
|
struct event_base* base = 0;
|
||||||
|
@ -366,19 +366,25 @@ bool StartHTTPServer(boost::thread_group& threadGroup)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPrint("http", "Starting HTTP server\n");
|
LogPrint("http", "Initialized HTTP server\n");
|
||||||
int workQueueDepth = std::max((long)GetArg("-rpcworkqueue", DEFAULT_HTTP_WORKQUEUE), 1L);
|
int workQueueDepth = std::max((long)GetArg("-rpcworkqueue", DEFAULT_HTTP_WORKQUEUE), 1L);
|
||||||
int rpcThreads = std::max((long)GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L);
|
LogPrintf("HTTP: creating work queue of depth %d\n", workQueueDepth);
|
||||||
LogPrintf("HTTP: creating work queue of depth %d and %d worker threads\n", workQueueDepth, rpcThreads);
|
|
||||||
workQueue = new WorkQueue<HTTPClosure>(workQueueDepth);
|
|
||||||
|
|
||||||
threadGroup.create_thread(boost::bind(&ThreadHTTP, base, http));
|
workQueue = new WorkQueue<HTTPClosure>(workQueueDepth);
|
||||||
|
eventBase = base;
|
||||||
|
eventHTTP = http;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartHTTPServer(boost::thread_group& threadGroup)
|
||||||
|
{
|
||||||
|
LogPrint("http", "Starting HTTP server\n");
|
||||||
|
int rpcThreads = std::max((long)GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L);
|
||||||
|
LogPrintf("HTTP: starting %d worker threads\n", rpcThreads);
|
||||||
|
threadGroup.create_thread(boost::bind(&ThreadHTTP, eventBase, eventHTTP));
|
||||||
|
|
||||||
for (int i = 0; i < rpcThreads; i++)
|
for (int i = 0; i < rpcThreads; i++)
|
||||||
threadGroup.create_thread(boost::bind(&HTTPWorkQueueRun, workQueue));
|
threadGroup.create_thread(boost::bind(&HTTPWorkQueueRun, workQueue));
|
||||||
|
|
||||||
eventBase = base;
|
|
||||||
eventHTTP = http;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,14 @@ struct event_base;
|
||||||
class CService;
|
class CService;
|
||||||
class HTTPRequest;
|
class HTTPRequest;
|
||||||
|
|
||||||
/** Start HTTP server */
|
/** Initialize HTTP server.
|
||||||
|
* Call this before RegisterHTTPHandler or EventBase().
|
||||||
|
*/
|
||||||
|
bool InitHTTPServer();
|
||||||
|
/** Start HTTP server.
|
||||||
|
* This is separate from InitHTTPServer to give users race-condition-free time
|
||||||
|
* to register their handlers between InitHTTPServer and StartHTTPServer.
|
||||||
|
*/
|
||||||
bool StartHTTPServer(boost::thread_group& threadGroup);
|
bool StartHTTPServer(boost::thread_group& threadGroup);
|
||||||
/** Interrupt HTTP server threads */
|
/** Interrupt HTTP server threads */
|
||||||
void InterruptHTTPServer();
|
void InterruptHTTPServer();
|
||||||
|
|
|
@ -618,7 +618,7 @@ bool AppInitServers(boost::thread_group& threadGroup)
|
||||||
{
|
{
|
||||||
RPCServer::OnStopped(&OnRPCStopped);
|
RPCServer::OnStopped(&OnRPCStopped);
|
||||||
RPCServer::OnPreCommand(&OnRPCPreCommand);
|
RPCServer::OnPreCommand(&OnRPCPreCommand);
|
||||||
if (!StartHTTPServer(threadGroup))
|
if (!InitHTTPServer())
|
||||||
return false;
|
return false;
|
||||||
if (!StartRPC())
|
if (!StartRPC())
|
||||||
return false;
|
return false;
|
||||||
|
@ -626,6 +626,8 @@ bool AppInitServers(boost::thread_group& threadGroup)
|
||||||
return false;
|
return false;
|
||||||
if (GetBoolArg("-rest", false) && !StartREST())
|
if (GetBoolArg("-rest", false) && !StartREST())
|
||||||
return false;
|
return false;
|
||||||
|
if (!StartHTTPServer(threadGroup))
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue