From e3d97d5f8ebfdd07831d4f5002648fb285999a67 Mon Sep 17 00:00:00 2001 From: Rafael Kitover Date: Sat, 24 Aug 2019 01:02:38 +0000 Subject: [PATCH] limit max thread count to 126 When the number of threads is higher than 126 the number of LMDB locks is exhausted and `ArmoryDB` dies with the error: ``` MDB_READERS_FULL: Environment maxreaders limit reached ``` See: https://github.com/lmdbjava/lmdbjava/issues/65#issuecomment-322761020 Replace the uses of `std::thread::hardware_concurrency()` with a new function `MAX_THREADS()` which limits the number of threads to `126`. This is a temporary fix, the real fix would be making sure the number of LMDB locks is sufficient. However, a configured value for the maximum number of threads would also be useful. Signed-off-by: Rafael Kitover --- cppForSwig/BDM_Server.cpp | 2 +- cppForSwig/BlockDataManagerConfig.cpp | 14 ++++++++++++++ cppForSwig/BlockDataManagerConfig.h | 4 +++- cppForSwig/Server.cpp | 4 ++-- cppForSwig/ZeroConf.cpp | 4 ++-- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/cppForSwig/BDM_Server.cpp b/cppForSwig/BDM_Server.cpp index 025f0b8f4..9489467bc 100644 --- a/cppForSwig/BDM_Server.cpp +++ b/cppForSwig/BDM_Server.cpp @@ -1848,7 +1848,7 @@ void Clients::init(BlockDataManagerThread* bdmT, unsigned innerThreadCount = 2; if (BlockDataManagerConfig::getDbType() == ARMORY_DB_SUPER && BlockDataManagerConfig::getOperationMode() != OPERATION_UNITTEST) - innerThreadCount = thread::hardware_concurrency(); + innerThreadCount = MAX_THREADS(); for (unsigned i = 0; i < innerThreadCount; i++) { controlThreads_.push_back(thread(innerthread)); diff --git a/cppForSwig/BlockDataManagerConfig.cpp b/cppForSwig/BlockDataManagerConfig.cpp index fee75f71f..acfefc77a 100644 --- a/cppForSwig/BlockDataManagerConfig.cpp +++ b/cppForSwig/BlockDataManagerConfig.cpp @@ -20,6 +20,20 @@ using namespace std; +size_t MAX_THREADS() +{ + size_t cpu_threads = std::thread::hardware_concurrency(); + + if (!cpu_threads) + return 1; + // there are only 126 LMDB locks by default + // FIXME: need to increase number of LMDB locks + else if (cpu_threads > 126) + return 126; + + return cpu_threads; +} + //////////////////////////////////////////////////////////////////////////////// // // NodeStatusStruct diff --git a/cppForSwig/BlockDataManagerConfig.h b/cppForSwig/BlockDataManagerConfig.h index ca064aef5..29b92dd9f 100644 --- a/cppForSwig/BlockDataManagerConfig.h +++ b/cppForSwig/BlockDataManagerConfig.h @@ -28,6 +28,8 @@ #define DEFAULT_ZCTHREAD_COUNT 100 #define WEBSOCKET_PORT 7681 +size_t MAX_THREADS(); + class BitcoinP2P; //////////////////////////////////////////////////////////////////////////////// @@ -66,7 +68,7 @@ struct BlockDataManagerConfig bool customBtcPort_ = false; unsigned ramUsage_ = 4; - unsigned threadCount_ = std::thread::hardware_concurrency(); + unsigned threadCount_ = MAX_THREADS(); unsigned zcThreadCount_ = DEFAULT_ZCTHREAD_COUNT; std::exception_ptr exceptionPtr_ = nullptr; diff --git a/cppForSwig/Server.cpp b/cppForSwig/Server.cpp index 85cb52045..0947eeedd 100644 --- a/cppForSwig/Server.cpp +++ b/cppForSwig/Server.cpp @@ -234,7 +234,7 @@ void WebSocketServer::start(BlockDataManagerThread* bdmT, instance->clientInterruptThread(); }; - unsigned parserThreads = thread::hardware_concurrency() / 4; + unsigned parserThreads = MAX_THREADS() / 4; if (parserThreads == 0) parserThreads = 1; for (unsigned i = 0; i < parserThreads; i++) @@ -1038,4 +1038,4 @@ void ClientConnection::processAEADHandshake(BinaryData msg) void ClientConnection::closeConnection() { run_->store(-1, memory_order_relaxed); -} \ No newline at end of file +} diff --git a/cppForSwig/ZeroConf.cpp b/cppForSwig/ZeroConf.cpp index 21251af03..4bee65c91 100644 --- a/cppForSwig/ZeroConf.cpp +++ b/cppForSwig/ZeroConf.cpp @@ -290,7 +290,7 @@ void ZeroConfContainer::preprocessZcMap( }; vector parserThreads; - for (unsigned i = 1; i < thread::hardware_concurrency(); i++) + for (unsigned i = 1; i < MAX_THREADS(); i++) parserThreads.push_back(thread(parserLdb)); parserLdb(); @@ -2111,4 +2111,4 @@ bool ZcUpdateBatch::hasData() const return true; return false; -} \ No newline at end of file +}