http: Wait for worker threads to exit
Add a WaitExit() call to http's WorkQueue to make it delete the work queue only when all worker threads stopped. This fixes a problem that was reproducable by pressing Ctrl-C during AppInit2: ``` /usr/include/boost/thread/pthread/condition_variable_fwd.hpp:81: boost::condition_variable::~condition_variable(): Assertion `!ret' failed. /usr/include/boost/thread/pthread/mutex.hpp:108: boost::mutex::~mutex(): Assertion `!posix::pthread_mutex_destroy(&m)' failed. ``` I was assuming that `threadGroup->join_all();` would always have been called when entering the Shutdown(). However this is not the case in bitcoind's AppInit2-non-zero-exit case "was left out intentionally here".
This commit is contained in:
parent
5e0c221356
commit
de9de2de36
@ -72,13 +72,35 @@ private:
|
||||
std::deque<WorkItem*> queue;
|
||||
bool running;
|
||||
size_t maxDepth;
|
||||
int numThreads;
|
||||
|
||||
/** RAII object to keep track of number of running worker threads */
|
||||
class ThreadCounter
|
||||
{
|
||||
public:
|
||||
WorkQueue &wq;
|
||||
ThreadCounter(WorkQueue &w): wq(w)
|
||||
{
|
||||
boost::lock_guard<boost::mutex> lock(wq.cs);
|
||||
wq.numThreads += 1;
|
||||
}
|
||||
~ThreadCounter()
|
||||
{
|
||||
boost::lock_guard<boost::mutex> lock(wq.cs);
|
||||
wq.numThreads -= 1;
|
||||
wq.cond.notify_all();
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
WorkQueue(size_t maxDepth) : running(true),
|
||||
maxDepth(maxDepth)
|
||||
maxDepth(maxDepth),
|
||||
numThreads(0)
|
||||
{
|
||||
}
|
||||
/* Precondition: worker threads have all stopped */
|
||||
/*( Precondition: worker threads have all stopped
|
||||
* (call WaitExit)
|
||||
*/
|
||||
~WorkQueue()
|
||||
{
|
||||
while (!queue.empty()) {
|
||||
@ -100,6 +122,7 @@ public:
|
||||
/** Thread function */
|
||||
void Run()
|
||||
{
|
||||
ThreadCounter count(*this);
|
||||
while (running) {
|
||||
WorkItem* i = 0;
|
||||
{
|
||||
@ -122,6 +145,13 @@ public:
|
||||
running = false;
|
||||
cond.notify_all();
|
||||
}
|
||||
/** Wait for worker threads to exit */
|
||||
void WaitExit()
|
||||
{
|
||||
boost::unique_lock<boost::mutex> lock(cs);
|
||||
while (numThreads > 0)
|
||||
cond.wait(lock);
|
||||
}
|
||||
|
||||
/** Return current depth of queue */
|
||||
size_t Depth()
|
||||
@ -434,7 +464,11 @@ void InterruptHTTPServer()
|
||||
void StopHTTPServer()
|
||||
{
|
||||
LogPrint("http", "Stopping HTTP server\n");
|
||||
delete workQueue;
|
||||
if (workQueue) {
|
||||
LogPrint("http", "Waiting for HTTP worker threads to exit\n");
|
||||
workQueue->WaitExit();
|
||||
delete workQueue;
|
||||
}
|
||||
if (eventHTTP) {
|
||||
evhttp_free(eventHTTP);
|
||||
eventHTTP = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user