Skip to content

Commit 3a174cd

Browse files
committed
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.
1 parent 6d2bc22 commit 3a174cd

File tree

3 files changed

+25
-10
lines changed

3 files changed

+25
-10
lines changed

src/httpserver.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ static void HTTPWorkQueueRun(WorkQueue<HTTPClosure>* queue)
320320
queue->Run();
321321
}
322322

323-
bool StartHTTPServer(boost::thread_group& threadGroup)
323+
bool InitHTTPServer()
324324
{
325325
struct evhttp* http = 0;
326326
struct event_base* base = 0;
@@ -366,19 +366,25 @@ bool StartHTTPServer(boost::thread_group& threadGroup)
366366
return false;
367367
}
368368

369-
LogPrint("http", "Starting HTTP server\n");
369+
LogPrint("http", "Initialized HTTP server\n");
370370
int workQueueDepth = std::max((long)GetArg("-rpcworkqueue", DEFAULT_HTTP_WORKQUEUE), 1L);
371-
int rpcThreads = std::max((long)GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L);
372-
LogPrintf("HTTP: creating work queue of depth %d and %d worker threads\n", workQueueDepth, rpcThreads);
371+
LogPrintf("HTTP: creating work queue of depth %d\n", workQueueDepth);
372+
373373
workQueue = new WorkQueue<HTTPClosure>(workQueueDepth);
374+
eventBase = base;
375+
eventHTTP = http;
376+
return true;
377+
}
374378

375-
threadGroup.create_thread(boost::bind(&ThreadHTTP, base, http));
379+
bool StartHTTPServer(boost::thread_group& threadGroup)
380+
{
381+
LogPrint("http", "Starting HTTP server\n");
382+
int rpcThreads = std::max((long)GetArg("-rpcthreads", DEFAULT_HTTP_THREADS), 1L);
383+
LogPrintf("HTTP: starting %d worker threads\n", rpcThreads);
384+
threadGroup.create_thread(boost::bind(&ThreadHTTP, eventBase, eventHTTP));
376385

377386
for (int i = 0; i < rpcThreads; i++)
378387
threadGroup.create_thread(boost::bind(&HTTPWorkQueueRun, workQueue));
379-
380-
eventBase = base;
381-
eventHTTP = http;
382388
return true;
383389
}
384390

src/httpserver.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,14 @@ struct event_base;
2020
class CService;
2121
class HTTPRequest;
2222

23-
/** Start HTTP server */
23+
/** Initialize HTTP server.
24+
* Call this before RegisterHTTPHandler or EventBase().
25+
*/
26+
bool InitHTTPServer();
27+
/** Start HTTP server.
28+
* This is separate from InitHTTPServer to give users race-condition-free time
29+
* to register their handlers between InitHTTPServer and StartHTTPServer.
30+
*/
2431
bool StartHTTPServer(boost::thread_group& threadGroup);
2532
/** Interrupt HTTP server threads */
2633
void InterruptHTTPServer();

src/init.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,14 +618,16 @@ bool AppInitServers(boost::thread_group& threadGroup)
618618
{
619619
RPCServer::OnStopped(&OnRPCStopped);
620620
RPCServer::OnPreCommand(&OnRPCPreCommand);
621-
if (!StartHTTPServer(threadGroup))
621+
if (!InitHTTPServer())
622622
return false;
623623
if (!StartRPC())
624624
return false;
625625
if (!StartHTTPRPC())
626626
return false;
627627
if (GetBoolArg("-rest", false) && !StartREST())
628628
return false;
629+
if (!StartHTTPServer(threadGroup))
630+
return false;
629631
return true;
630632
}
631633

0 commit comments

Comments
 (0)