From a27281591da9d4023d78f06823adaf2a7d51f724 Mon Sep 17 00:00:00 2001 From: Nicky Date: Fri, 7 Jun 2019 11:11:56 +0200 Subject: Replace boost::fibers::unbuffered_channel with boost::fibers::buffered_channel. Using boost::fibers::unbuffered_channel can block the mainthread when calling mPendingCoprocs.push (LLCoprocedurePool::enqueueCoprocedure) From the documentation: - If a fiber attempts to send a value through an unbuffered channel and no fiber is waiting to receive the value, the channel will block the sending fiber. This can happen if LLCoprocedurePool::coprocedureInvokerCoro is running a coroutine and this coroutine calls yield, resuming the viewers main loop. If inside the main loop someone calls LLCoprocedurePool::enqueueCoprocedure now push will block, as there's no one waiting for a result right now. The wait would be in LLCoprocedurePool::coprocedureInvokerCoro at the start of the while loop, but we have not reached that yet again as LLCoprocedurePool::coprocedureInvokerCoro did yield before reaching pop_wait_for. The result is a deadlock. boost::fibers::buffered_channel will not block as long as there's space in the channel. A size of 4096 (DEFAULT_QUEUE_SIZE) should be plenty enough for this. --- indra/llmessage/llcoproceduremanager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'indra/llmessage/llcoproceduremanager.cpp') diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp index 13ee12b5bb..bc7c982756 100644 --- a/indra/llmessage/llcoproceduremanager.cpp +++ b/indra/llmessage/llcoproceduremanager.cpp @@ -34,7 +34,7 @@ #include #include -#include +#include #include "llexception.h" #include "stringize.h" @@ -48,6 +48,7 @@ static const std::map DefaultPoolSizes{ }; static const U32 DEFAULT_POOL_SIZE = 5; +static const U32 DEFAULT_QUEUE_SIZE = 4096; //========================================================================= class LLCoprocedurePool: private boost::noncopyable @@ -112,7 +113,7 @@ private: // we use a deque here rather than std::queue since we want to be able to // iterate through the queue and potentially erase an entry from the middle. - typedef boost::fibers::unbuffered_channel CoprocQueue_t; + typedef boost::fibers::buffered_channel CoprocQueue_t; typedef std::map ActiveCoproc_t; std::string mPoolName; @@ -283,7 +284,7 @@ void LLCoprocedureManager::close(const std::string &pool) LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size): mPoolName(poolName), mPoolSize(size), - mPendingCoprocs(), + mPendingCoprocs(DEFAULT_QUEUE_SIZE), //mShutdown(false), mCoroMapping(), mHTTPPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID) -- cgit v1.2.3