Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <logging.h>6#include <util/threadpool.h>8#include <test/fuzz/FuzzedDataProvider.h>9#include <test/fuzz/fuzz.h>11#include <atomic>12#include <future>13#include <queue>15struct ExpectedException : std::runtime_error {16explicit ExpectedException(const std::string& msg) : std::runtime_error(msg) {}17};19struct ThrowTask {20void operator()() const { throw ExpectedException("fail"); }21};23struct CounterTask {24std::atomic_uint32_t& m_counter;25explicit CounterTask(std::atomic_uint32_t& counter) : m_counter{counter} {}26void operator()() const { m_counter.fetch_add(1, std::memory_order_relaxed); }27};29// Waits for a future to complete. Increments 'fail_counter' if the expected exception is thrown.30static void GetFuture(std::future<void>& future, uint32_t& fail_counter)31{32try {33future.get();34} catch (const ExpectedException&) {35fail_counter++;36} catch (...) {37assert(false && "Unexpected exception type");38}39}41// Global thread pool for fuzzing. Persisting it across iterations prevents42// the excessive thread creation/destruction overhead that can lead to43// instability in the fuzzing environment.44// This is also how we use it in the app's lifecycle.45ThreadPool g_pool{"fuzz"};46// Global to verify we always have the same number of threads.47size_t g_num_workers = 3;49static void StartPoolIfNeeded()50{51if (g_pool.WorkersCount() == g_num_workers) return;52g_pool.Start(g_num_workers);53}55static void setup_threadpool_test()56{57// Disable logging entirely. It seems to cause memory leaks.58LogInstance().DisableLogging();59}61FUZZ_TARGET(threadpool, .init = setup_threadpool_test)62{63// Because LibAFL calls fork() after calling the init setup function,64// the child processes end up having one thread active and no workers.65// To work around this limitation, start thread pool inside the first runner.66StartPoolIfNeeded();68FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());70const uint32_t num_tasks = fuzzed_data_provider.ConsumeIntegralInRange<uint32_t>(0, 1024);71assert(g_pool.WorkersCount() == g_num_workers);72assert(g_pool.WorkQueueSize() == 0);74// Counters75std::atomic_uint32_t task_counter{0};76uint32_t fail_counter{0};77uint32_t expected_task_counter{0};78uint32_t expected_fail_tasks{0};80std::queue<std::future<void>> futures;81for (uint32_t i = 0; i < num_tasks; ++i) {82const bool will_throw = fuzzed_data_provider.ConsumeBool();83const bool wait_immediately = fuzzed_data_provider.ConsumeBool();85std::future<void> fut;86if (will_throw) {87expected_fail_tasks++;88fut = *Assert(g_pool.Submit(ThrowTask{}));89} else {90expected_task_counter++;91fut = *Assert(g_pool.Submit(CounterTask{task_counter}));92}94// If caller wants to wait immediately, consume the future here (safe).95if (wait_immediately) {96// Waits for this task to complete immediately; prior queued tasks may also complete97// as they were queued earlier.98GetFuture(fut, fail_counter);99} else {100// Store task for a posterior check101futures.emplace(std::move(fut));102}103}105// Drain remaining futures106while (!futures.empty()) {107auto fut = std::move(futures.front());108futures.pop();109GetFuture(fut, fail_counter);110}112assert(g_pool.WorkQueueSize() == 0);113assert(task_counter.load() == expected_task_counter);114assert(fail_counter == expected_fail_tasks);115}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.