From 78cb7078381df303649c2454db4dbc1a89e7f79c Mon Sep 17 00:00:00 2001 From: marta-lokhova Date: Mon, 4 Nov 2024 12:01:09 -0800 Subject: [PATCH 1/2] Enable background overlay by default, drop 'experimental' prefix --- src/herder/test/HerderTests.cpp | 2 +- src/main/ApplicationImpl.cpp | 4 ++-- src/main/Config.cpp | 15 ++++++++++----- src/main/Config.h | 2 +- src/overlay/Peer.h | 3 +-- src/overlay/PeerDoor.cpp | 7 +++---- src/overlay/TCPPeer.cpp | 2 +- src/overlay/test/TCPPeerTests.cpp | 8 ++++---- src/simulation/Simulation.cpp | 4 ++-- 9 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/herder/test/HerderTests.cpp b/src/herder/test/HerderTests.cpp index acdf87a2a7..fcc07519f4 100644 --- a/src/herder/test/HerderTests.cpp +++ b/src/herder/test/HerderTests.cpp @@ -3361,7 +3361,7 @@ TEST_CASE("overlay parallel processing") Topologies::core(4, 1, Simulation::OVER_TCP, networkID, [](int i) { auto cfg = getTestConfig(i); cfg.TESTING_UPGRADE_MAX_TX_SET_SIZE = 100; - cfg.EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING = true; + cfg.BACKGROUND_OVERLAY_PROCESSING = true; return cfg; }); simulation->startAllNodes(); diff --git a/src/main/ApplicationImpl.cpp b/src/main/ApplicationImpl.cpp index 4deada6568..67f7f5dfd4 100644 --- a/src/main/ApplicationImpl.cpp +++ b/src/main/ApplicationImpl.cpp @@ -96,7 +96,7 @@ ApplicationImpl::ApplicationImpl(VirtualClock& clock, Config const& cfg) mEvictionIOContext ? std::make_unique(*mEvictionIOContext) : nullptr) - , mOverlayIOContext(mConfig.EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING + , mOverlayIOContext(mConfig.BACKGROUND_OVERLAY_PROCESSING ? std::make_unique(1) : nullptr) , mOverlayWork(mOverlayIOContext ? std::make_unique( @@ -181,7 +181,7 @@ ApplicationImpl::ApplicationImpl(VirtualClock& clock, Config const& cfg) mWorkerThreads.emplace_back(std::move(thread)); } - if (mConfig.EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING) + if (mConfig.BACKGROUND_OVERLAY_PROCESSING) { // Keep priority unchanged as overlay processes time-sensitive tasks mOverlayThread = std::thread{[this]() { mOverlayIOContext->run(); }}; diff --git a/src/main/Config.cpp b/src/main/Config.cpp index 927883ee8d..2208e68949 100644 --- a/src/main/Config.cpp +++ b/src/main/Config.cpp @@ -162,7 +162,7 @@ Config::Config() : NODE_SEED(SecretKey::random()) CATCHUP_COMPLETE = false; CATCHUP_RECENT = 0; EXPERIMENTAL_PRECAUTION_DELAY_META = false; - EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING = false; + BACKGROUND_OVERLAY_PROCESSING = true; DEPRECATED_SQL_LEDGER_STATE = false; BUCKETLIST_DB_INDEX_PAGE_SIZE_EXPONENT = 14; // 2^14 == 16 kb BUCKETLIST_DB_INDEX_CUTOFF = 20; // 20 mb @@ -1066,9 +1066,14 @@ Config::processConfig(std::shared_ptr t) }}, {"EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING", [&]() { - EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING = - readBool(item); + CLOG_WARNING(Overlay, + "EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING " + "is deprecated. Use " + "BACKGROUND_OVERLAY_PROCESSING instead"); + BACKGROUND_OVERLAY_PROCESSING = readBool(item); }}, + {"BACKGROUND_OVERLAY_PROCESSING", + [&]() { BACKGROUND_OVERLAY_PROCESSING = readBool(item); }}, {"BACKGROUND_EVICTION_SCAN", [&]() { BACKGROUND_EVICTION_SCAN = readBool(item); }}, // TODO: Flag is no longer supported, remove in next release. @@ -1984,9 +1989,9 @@ Config::logBasicInfo() LOG_INFO(DEFAULT_LOG, "MAX_INBOUND_PENDING_CONNECTIONS: {}", MAX_INBOUND_PENDING_CONNECTIONS); LOG_INFO(DEFAULT_LOG, - "EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING=" + "BACKGROUND_OVERLAY_PROCESSING=" "{}", - EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING ? "true" : "false"); + BACKGROUND_OVERLAY_PROCESSING ? "true" : "false"); } void diff --git a/src/main/Config.h b/src/main/Config.h index 600a349259..ef52aaddcb 100644 --- a/src/main/Config.h +++ b/src/main/Config.h @@ -405,7 +405,7 @@ class Config : public std::enable_shared_from_this size_t BUCKETLIST_DB_INDEX_CUTOFF; // Enable parallel processing of overlay operations (experimental) - bool EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING; + bool BACKGROUND_OVERLAY_PROCESSING; // When set to true, BucketListDB indexes are persisted on-disk so that the // BucketList does not need to be reindexed on startup. Defaults to true. diff --git a/src/overlay/Peer.h b/src/overlay/Peer.h index a59cdbb72b..0f0ee1c33c 100644 --- a/src/overlay/Peer.h +++ b/src/overlay/Peer.h @@ -207,8 +207,7 @@ class Peer : public std::enable_shared_from_this, virtual bool useBackgroundThread() const { - return mAppConnector.getConfig() - .EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING; + return mAppConnector.getConfig().BACKGROUND_OVERLAY_PROCESSING; } void initialize(PeerBareAddress const& address); diff --git a/src/overlay/PeerDoor.cpp b/src/overlay/PeerDoor.cpp index 23a9ead14d..a930446fd7 100644 --- a/src/overlay/PeerDoor.cpp +++ b/src/overlay/PeerDoor.cpp @@ -65,10 +65,9 @@ PeerDoor::acceptNextPeer() // io_context on main (as long as the socket is not accessed by multiple // threads simultaneously, or the caller manually synchronizes access to the // socket). - auto& ioContext = - mApp.getConfig().EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING - ? mApp.getOverlayIOContext() - : mApp.getClock().getIOContext(); + auto& ioContext = mApp.getConfig().BACKGROUND_OVERLAY_PROCESSING + ? mApp.getOverlayIOContext() + : mApp.getClock().getIOContext(); auto sock = make_shared(ioContext, TCPPeer::BUFSZ); mAcceptor.async_accept(sock->next_layer(), [this, sock](asio::error_code const& ec) { diff --git a/src/overlay/TCPPeer.cpp b/src/overlay/TCPPeer.cpp index bd8d2885ca..f3129f94ab 100644 --- a/src/overlay/TCPPeer.cpp +++ b/src/overlay/TCPPeer.cpp @@ -54,7 +54,7 @@ TCPPeer::initiate(Application& app, PeerBareAddress const& address) releaseAssert(address.getType() == PeerBareAddress::Type::IPv4); CLOG_DEBUG(Overlay, "TCPPeer:initiate to {}", address.toString()); - auto& ioContext = app.getConfig().EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING + auto& ioContext = app.getConfig().BACKGROUND_OVERLAY_PROCESSING ? app.getOverlayIOContext() : app.getClock().getIOContext(); auto socket = make_shared(ioContext, BUFSZ); diff --git a/src/overlay/test/TCPPeerTests.cpp b/src/overlay/test/TCPPeerTests.cpp index f43613f8a3..c8b35c62d7 100644 --- a/src/overlay/test/TCPPeerTests.cpp +++ b/src/overlay/test/TCPPeerTests.cpp @@ -26,7 +26,7 @@ TEST_CASE("TCPPeer lifetime", "[overlay]") cfg.MAX_OUTBOUND_PENDING_CONNECTIONS = i % 2; cfg.TARGET_PEER_CONNECTIONS = i % 2; cfg.MAX_ADDITIONAL_PEER_CONNECTIONS = i % 2; - cfg.EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING = true; + cfg.BACKGROUND_OVERLAY_PROCESSING = true; return cfg; }); @@ -92,7 +92,7 @@ TEST_CASE("TCPPeer can communicate", "[overlay]") { cfgGen = [](int i) { Config cfg = getTestConfig(i); - cfg.EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING = true; + cfg.BACKGROUND_OVERLAY_PROCESSING = true; return cfg; }; } @@ -100,7 +100,7 @@ TEST_CASE("TCPPeer can communicate", "[overlay]") { cfgGen = [](int i) { Config cfg = getTestConfig(i); - cfg.EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING = false; + cfg.BACKGROUND_OVERLAY_PROCESSING = false; return cfg; }; } @@ -183,7 +183,7 @@ TEST_CASE("TCPPeer read malformed messages", "[overlay]") Simulation::pointer s = std::make_shared( Simulation::OVER_TCP, networkID, [](int i) { Config cfg = getTestConfig(i); - cfg.EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING = true; + cfg.BACKGROUND_OVERLAY_PROCESSING = true; // Slow down the main thread to delay drops cfg.ARTIFICIALLY_SLEEP_MAIN_THREAD_FOR_TESTING = std::chrono::milliseconds(300); diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index 0818922f6a..f6b91cbf2e 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -41,7 +41,7 @@ Simulation::Simulation(Mode mode, Hash const& networkID, ConfigGen confGen, , mQuorumSetAdjuster(qSetAdjust) { auto cfg = newConfig(); - auto& parallel = cfg.EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING; + auto& parallel = cfg.BACKGROUND_OVERLAY_PROCESSING; parallel = parallel && mVirtualClockMode == VirtualClock::REAL_TIME; mIdleApp = Application::create(mClock, cfg); mPeerMap.emplace(mIdleApp->getConfig().PEER_PORT, mIdleApp); @@ -99,7 +99,7 @@ Simulation::addNode(SecretKey nodeKey, SCPQuorumSet qSet, Config const* cfg2, cfg->adjust(); cfg->NODE_SEED = nodeKey; cfg->MANUAL_CLOSE = false; - auto& parallel = cfg->EXPERIMENTAL_BACKGROUND_OVERLAY_PROCESSING; + auto& parallel = cfg->BACKGROUND_OVERLAY_PROCESSING; parallel = parallel && mVirtualClockMode == VirtualClock::REAL_TIME; if (mQuorumSetAdjuster) From 421ac1cd713c2d83bf8329730d89ff4421ecaaef Mon Sep 17 00:00:00 2001 From: marta-lokhova Date: Wed, 20 Nov 2024 14:41:07 -0800 Subject: [PATCH 2/2] Suppress a Tsan false positive --- src/bucket/BucketManagerImpl.cpp | 58 +++++++++++++++--------------- src/bucket/BucketManagerImpl.h | 3 ++ src/main/Config.cpp | 2 +- src/main/Config.h | 2 +- src/overlay/OverlayManagerImpl.cpp | 22 ++++++------ 5 files changed, 45 insertions(+), 42 deletions(-) diff --git a/src/bucket/BucketManagerImpl.cpp b/src/bucket/BucketManagerImpl.cpp index b228f93e83..3fbe228b64 100644 --- a/src/bucket/BucketManagerImpl.cpp +++ b/src/bucket/BucketManagerImpl.cpp @@ -91,7 +91,7 @@ void BucketManagerImpl::initialize() { ZoneScoped; - std::string d = mApp.getConfig().BUCKET_DIR_PATH; + std::string d = mConfig.BUCKET_DIR_PATH; if (!fs::exists(d)) { @@ -122,17 +122,17 @@ BucketManagerImpl::initialize() mLockedBucketDir = std::make_unique(d); mTmpDirManager = std::make_unique(d + "/tmp"); - if (mApp.getConfig().MODE_ENABLES_BUCKETLIST) + if (mConfig.MODE_ENABLES_BUCKETLIST) { mBucketList = std::make_unique(); - if (mApp.getConfig().isUsingBucketListDB()) + if (mConfig.isUsingBucketListDB()) { mSnapshotManager = std::make_unique( mApp, std::make_unique(*mBucketList, LedgerHeader()), - mApp.getConfig().QUERY_SNAPSHOT_LEDGERS); + mConfig.QUERY_SNAPSHOT_LEDGERS); } } @@ -141,11 +141,10 @@ BucketManagerImpl::initialize() // BUCKET_DIR_PATH, HISTORY_FILE_TYPE_SCP is persisted to the database // so create the remaining ledger header, transactions and results // directories - createPublishDir(FileType::HISTORY_FILE_TYPE_LEDGER, mApp.getConfig()); - createPublishDir(FileType::HISTORY_FILE_TYPE_TRANSACTIONS, - mApp.getConfig()); - createPublishDir(FileType::HISTORY_FILE_TYPE_RESULTS, mApp.getConfig()); - HistoryManager::createPublishQueueDir(mApp.getConfig()); + createPublishDir(FileType::HISTORY_FILE_TYPE_LEDGER, mConfig); + createPublishDir(FileType::HISTORY_FILE_TYPE_TRANSACTIONS, mConfig); + createPublishDir(FileType::HISTORY_FILE_TYPE_RESULTS, mConfig); + HistoryManager::createPublishQueueDir(mConfig); } void @@ -201,6 +200,7 @@ BucketManagerImpl::BucketManagerImpl(Application& app) // mode does not use minimal DB , mDeleteEntireBucketDirInDtor( app.getConfig().isInMemoryModeWithoutMinimalDB()) + , mConfig(app.getConfig()) { for (uint32_t t = static_cast(LedgerEntryTypeAndDurability::ACCOUNT); @@ -299,7 +299,7 @@ void BucketManagerImpl::deleteEntireBucketDir() { ZoneScoped; - std::string d = mApp.getConfig().BUCKET_DIR_PATH; + std::string d = mConfig.BUCKET_DIR_PATH; if (fs::exists(d)) { // First clean out the contents of the tmpdir, as usual. @@ -332,7 +332,7 @@ BucketManagerImpl::deleteTmpDirAndUnlockBucketDir() // Then delete the lockfile $BUCKET_DIR_PATH/stellar-core.lock if (mLockedBucketDir) { - std::string d = mApp.getConfig().BUCKET_DIR_PATH; + std::string d = mConfig.BUCKET_DIR_PATH; std::string lock = d + "/" + kLockFilename; releaseAssert(fs::exists(lock)); fs::unlockFile(lock); @@ -343,14 +343,14 @@ BucketManagerImpl::deleteTmpDirAndUnlockBucketDir() BucketList& BucketManagerImpl::getBucketList() { - releaseAssertOrThrow(mApp.getConfig().MODE_ENABLES_BUCKETLIST); + releaseAssertOrThrow(mConfig.MODE_ENABLES_BUCKETLIST); return *mBucketList; } BucketSnapshotManager& BucketManagerImpl::getBucketSnapshotManager() const { - releaseAssertOrThrow(mApp.getConfig().isUsingBucketListDB()); + releaseAssertOrThrow(mConfig.isUsingBucketListDB()); releaseAssert(mSnapshotManager); return *mSnapshotManager; } @@ -476,7 +476,7 @@ BucketManagerImpl::renameBucketDirFile(std::filesystem::path const& src, std::filesystem::path const& dst) { ZoneScoped; - if (mApp.getConfig().DISABLE_XDR_FSYNC) + if (mConfig.DISABLE_XDR_FSYNC) { return rename(src.string().c_str(), dst.string().c_str()) == 0; } @@ -492,7 +492,7 @@ BucketManagerImpl::adoptFileAsBucket(std::string const& filename, std::unique_ptr index) { ZoneScoped; - releaseAssertOrThrow(mApp.getConfig().MODE_ENABLES_BUCKETLIST); + releaseAssertOrThrow(mConfig.MODE_ENABLES_BUCKETLIST); std::lock_guard lock(mBucketMutex); if (mergeKey) @@ -566,7 +566,7 @@ BucketManagerImpl::adoptFileAsBucket(std::string const& filename, void BucketManagerImpl::noteEmptyMergeOutput(MergeKey const& mergeKey) { - releaseAssertOrThrow(mApp.getConfig().MODE_ENABLES_BUCKETLIST); + releaseAssertOrThrow(mConfig.MODE_ENABLES_BUCKETLIST); // We _do_ want to remove the mergeKey from mLiveFutures, both so that that // map does not grow without bound and more importantly so that we drop the @@ -681,7 +681,7 @@ BucketManagerImpl::putMergeFuture( MergeKey const& key, std::shared_future> wp) { ZoneScoped; - releaseAssertOrThrow(mApp.getConfig().MODE_ENABLES_BUCKETLIST); + releaseAssertOrThrow(mConfig.MODE_ENABLES_BUCKETLIST); std::lock_guard lock(mBucketMutex); CLOG_TRACE( Bucket, @@ -704,7 +704,7 @@ BucketManagerImpl::getBucketListReferencedBuckets() const { ZoneScoped; std::set referenced; - if (!mApp.getConfig().MODE_ENABLES_BUCKETLIST) + if (!mConfig.MODE_ENABLES_BUCKETLIST) { return referenced; } @@ -743,7 +743,7 @@ BucketManagerImpl::getAllReferencedBuckets() const { ZoneScoped; auto referenced = getBucketListReferencedBuckets(); - if (!mApp.getConfig().MODE_ENABLES_BUCKETLIST) + if (!mConfig.MODE_ENABLES_BUCKETLIST) { return referenced; } @@ -788,7 +788,7 @@ void BucketManagerImpl::cleanupStaleFiles() { ZoneScoped; - if (mApp.getConfig().DISABLE_BUCKET_GC) + if (mConfig.DISABLE_BUCKET_GC) { return; } @@ -867,7 +867,7 @@ BucketManagerImpl::forgetUnreferencedBuckets() CLOG_TRACE(Bucket, "BucketManager::forgetUnreferencedBuckets dropping {}", filename); - if (!filename.empty() && !mApp.getConfig().DISABLE_BUCKET_GC) + if (!filename.empty() && !mConfig.DISABLE_BUCKET_GC) { CLOG_TRACE(Bucket, "removing bucket file: {}", filename); std::filesystem::remove(filename); @@ -974,7 +974,7 @@ BucketManagerImpl::snapshotLedger(LedgerHeader& currentHeader) { ZoneScoped; Hash hash; - if (mApp.getConfig().MODE_ENABLES_BUCKETLIST) + if (mConfig.MODE_ENABLES_BUCKETLIST) { hash = mBucketList->getHash(); } @@ -1017,7 +1017,7 @@ BucketManagerImpl::scanForEvictionLegacy(AbstractLedgerTxn& ltx, void BucketManagerImpl::startBackgroundEvictionScan(uint32_t ledgerSeq) { - releaseAssert(mApp.getConfig().isUsingBucketListDB()); + releaseAssert(mConfig.isUsingBucketListDB()); releaseAssert(mSnapshotManager); releaseAssert(!mEvictionFuture.valid()); releaseAssert(mEvictionStatistics); @@ -1176,7 +1176,7 @@ BucketManagerImpl::assumeState(HistoryArchiveState const& has, uint32_t maxProtocolVersion, bool restartMerges) { ZoneScoped; - releaseAssertOrThrow(mApp.getConfig().MODE_ENABLES_BUCKETLIST); + releaseAssertOrThrow(mConfig.MODE_ENABLES_BUCKETLIST); for (uint32_t i = 0; i < BucketList::kNumLevels; ++i) { @@ -1203,7 +1203,7 @@ BucketManagerImpl::assumeState(HistoryArchiveState const& has, // Buckets on the BucketList should always be indexed when // BucketListDB enabled - if (mApp.getConfig().isUsingBucketListDB()) + if (mConfig.isUsingBucketListDB()) { releaseAssert(curr->isEmpty() || curr->isIndexed()); releaseAssert(snap->isEmpty() || snap->isIndexed()); @@ -1328,7 +1328,7 @@ BucketManagerImpl::mergeBuckets(HistoryArchiveState const& has) BucketMetadata meta; MergeCounters mc; auto& ctx = mApp.getClock().getIOContext(); - meta.ledgerVersion = mApp.getConfig().LEDGER_PROTOCOL_VERSION; + meta.ledgerVersion = mConfig.LEDGER_PROTOCOL_VERSION; BucketOutputIterator out(getTmpDir(), /*keepDeadEntries=*/false, meta, mc, ctx, /*doFsync=*/true); for (auto const& pair : ledgerMap) @@ -1539,13 +1539,13 @@ BucketManagerImpl::scheduleVerifyReferencedBucketsWork() Config const& BucketManagerImpl::getConfig() const { - return mApp.getConfig(); + return mConfig; } std::shared_ptr BucketManagerImpl::getSearchableBucketListSnapshot() { - releaseAssert(mApp.getConfig().isUsingBucketListDB()); + releaseAssert(mConfig.isUsingBucketListDB()); // Any other threads must maintain their own snapshot releaseAssert(threadIsMain()); if (!mSearchableBucketListSnapshot) @@ -1560,7 +1560,7 @@ BucketManagerImpl::getSearchableBucketListSnapshot() void BucketManagerImpl::reportBucketEntryCountMetrics() { - if (!mApp.getConfig().isUsingBucketListDB()) + if (!mConfig.isUsingBucketListDB()) { return; } diff --git a/src/bucket/BucketManagerImpl.h b/src/bucket/BucketManagerImpl.h index 50b6479ede..a1d2569ae1 100644 --- a/src/bucket/BucketManagerImpl.h +++ b/src/bucket/BucketManagerImpl.h @@ -3,6 +3,7 @@ #include "bucket/BucketList.h" #include "bucket/BucketManager.h" #include "bucket/BucketMergeMap.h" +#include "main/Config.h" #include "xdr/Stellar-ledger.h" #include @@ -72,6 +73,8 @@ class BucketManagerImpl : public BucketManager std::future mEvictionFuture{}; bool const mDeleteEntireBucketDirInDtor; + // Copy app's config for thread-safe access + Config const mConfig; // Records bucket-merges that are currently _live_ in some FutureBucket, in // the sense of either running, or finished (with or without the diff --git a/src/main/Config.cpp b/src/main/Config.cpp index 2208e68949..3abb600a2b 100644 --- a/src/main/Config.cpp +++ b/src/main/Config.cpp @@ -1975,7 +1975,7 @@ Config::adjust() } void -Config::logBasicInfo() +Config::logBasicInfo() const { LOG_INFO(DEFAULT_LOG, "Connection effective settings:"); LOG_INFO(DEFAULT_LOG, "TARGET_PEER_CONNECTIONS: {}", diff --git a/src/main/Config.h b/src/main/Config.h index ef52aaddcb..3d8b7df194 100644 --- a/src/main/Config.h +++ b/src/main/Config.h @@ -739,7 +739,7 @@ class Config : public std::enable_shared_from_this bool isPersistingBucketListDBIndexes() const; bool modeStoresAllHistory() const; bool modeStoresAnyHistory() const; - void logBasicInfo(); + void logBasicInfo() const; void setNoListen(); void setNoPublish(); diff --git a/src/overlay/OverlayManagerImpl.cpp b/src/overlay/OverlayManagerImpl.cpp index 5bbc181901..a777cee998 100644 --- a/src/overlay/OverlayManagerImpl.cpp +++ b/src/overlay/OverlayManagerImpl.cpp @@ -497,17 +497,17 @@ OverlayManagerImpl::triggerPeerResolution() // Trigger DNS resolution on the background thread using task_t = std::packaged_task; - std::shared_ptr task = std::make_shared([this]() { - if (!this->mShuttingDown) - { - auto known = resolvePeers(this->mApp.getConfig().KNOWN_PEERS); - auto preferred = - resolvePeers(this->mApp.getConfig().PREFERRED_PEERS); - return ResolvedPeers{known.first, preferred.first, - known.second || preferred.second}; - } - return ResolvedPeers{{}, {}, false}; - }); + std::shared_ptr task = + std::make_shared([this, cfg = mApp.getConfig()]() { + if (!this->mShuttingDown) + { + auto known = resolvePeers(cfg.KNOWN_PEERS); + auto preferred = resolvePeers(cfg.PREFERRED_PEERS); + return ResolvedPeers{known.first, preferred.first, + known.second || preferred.second}; + } + return ResolvedPeers{{}, {}, false}; + }); mResolvedPeers = task->get_future(); mApp.postOnBackgroundThread(bind(&task_t::operator(), task),