diff options
-rw-r--r-- | doc/developer-notes.md | 14 | ||||
-rw-r--r-- | src/logging.cpp | 2 | ||||
-rw-r--r-- | src/logging.h | 2 | ||||
-rw-r--r-- | src/net.h | 2 | ||||
-rw-r--r-- | src/rpc/blockchain.cpp | 4 | ||||
-rw-r--r-- | src/sync.h | 5 | ||||
-rw-r--r-- | src/test/checkqueue_tests.cpp | 10 | ||||
-rwxr-xr-x | test/functional/rpc_misc.py | 3 |
8 files changed, 34 insertions, 8 deletions
diff --git a/doc/developer-notes.md b/doc/developer-notes.md index bfb64093e1..5bb927c44e 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -17,6 +17,7 @@ Developer Notes - [`debug.log`](#debuglog) - [Signet, testnet, and regtest modes](#signet-testnet-and-regtest-modes) - [DEBUG_LOCKORDER](#debug_lockorder) + - [DEBUG_LOCKCONTENTION](#debug_lockcontention) - [Valgrind suppressions file](#valgrind-suppressions-file) - [Compiling for test coverage](#compiling-for-test-coverage) - [Performance profiling with perf](#performance-profiling-with-perf) @@ -316,6 +317,19 @@ configure option adds `-DDEBUG_LOCKORDER` to the compiler flags. This inserts run-time checks to keep track of which locks are held and adds warnings to the `debug.log` file if inconsistencies are detected. +### DEBUG_LOCKCONTENTION + +Defining `DEBUG_LOCKCONTENTION` adds a "lock" logging category to the logging +RPC that, when enabled, logs the location and duration of each lock contention +to the `debug.log` file. + +To enable it, run configure with `-DDEBUG_LOCKCONTENTION` added to your +CPPFLAGS, e.g. `CPPFLAGS="-DDEBUG_LOCKCONTENTION"`, then build and run bitcoind. + +You can then use the `-debug=lock` configuration option at bitcoind startup or +`bitcoin-cli logging '["lock"]'` at runtime to turn on lock contention logging. +It can be toggled off again with `bitcoin-cli logging [] '["lock"]'`. + ### Assertions and Checks The util file `src/util/check.h` offers helpers to protect against coding and diff --git a/src/logging.cpp b/src/logging.cpp index 764941c8ea..a5e5fdb4cd 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -160,7 +160,9 @@ const CLogCategoryDesc LogCategories[] = {BCLog::VALIDATION, "validation"}, {BCLog::I2P, "i2p"}, {BCLog::IPC, "ipc"}, +#ifdef DEBUG_LOCKCONTENTION {BCLog::LOCK, "lock"}, +#endif {BCLog::UTIL, "util"}, {BCLog::BLOCKSTORE, "blockstorage"}, {BCLog::ALL, "1"}, diff --git a/src/logging.h b/src/logging.h index 710e6c4c32..ae8cad906c 100644 --- a/src/logging.h +++ b/src/logging.h @@ -60,7 +60,9 @@ namespace BCLog { VALIDATION = (1 << 21), I2P = (1 << 22), IPC = (1 << 23), +#ifdef DEBUG_LOCKCONTENTION LOCK = (1 << 24), +#endif UTIL = (1 << 25), BLOCKSTORE = (1 << 26), ALL = ~(uint32_t)0, @@ -13,6 +13,7 @@ #include <crypto/siphash.h> #include <hash.h> #include <i2p.h> +#include <logging.h> #include <net_permissions.h> #include <netaddress.h> #include <netbase.h> @@ -32,6 +33,7 @@ #include <cstdint> #include <deque> #include <functional> +#include <list> #include <map> #include <memory> #include <optional> diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index ef572cf8f8..c066f6f569 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -795,7 +795,7 @@ static RPCHelpMan getblockfrompeer() "Subsequent calls for the same block and a new peer will cause the response from the previous peer to be ignored.\n\n" "Returns an empty JSON object if the request was successfully scheduled.", { - {"block_hash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash to try to fetch"}, + {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash to try to fetch"}, {"peer_id", RPCArg::Type::NUM, RPCArg::Optional::NO, "The peer to fetch it from (see getpeerinfo for peer IDs)"}, }, RPCResult{RPCResult::Type::OBJ, "", /*optional=*/false, "", {}}, @@ -809,7 +809,7 @@ static RPCHelpMan getblockfrompeer() ChainstateManager& chainman = EnsureChainman(node); PeerManager& peerman = EnsurePeerman(node); - const uint256& block_hash{ParseHashV(request.params[0], "block_hash")}; + const uint256& block_hash{ParseHashV(request.params[0], "blockhash")}; const NodeId peer_id{request.params[1].get_int64()}; const CBlockIndex* const index = WITH_LOCK(cs_main, return chainman.m_blockman.LookupBlockIndex(block_hash);); diff --git a/src/sync.h b/src/sync.h index 85000a9151..af7595e6fa 100644 --- a/src/sync.h +++ b/src/sync.h @@ -6,8 +6,11 @@ #ifndef BITCOIN_SYNC_H #define BITCOIN_SYNC_H +#ifdef DEBUG_LOCKCONTENTION #include <logging.h> #include <logging/timer.h> +#endif + #include <threadsafety.h> #include <util/macros.h> @@ -136,8 +139,10 @@ private: void Enter(const char* pszName, const char* pszFile, int nLine) { EnterCritical(pszName, pszFile, nLine, Base::mutex()); +#ifdef DEBUG_LOCKCONTENTION if (Base::try_lock()) return; LOG_TIME_MICROS_WITH_CATEGORY(strprintf("lock contention %s, %s:%d", pszName, pszFile, nLine), BCLog::LOCK); +#endif Base::lock(); } diff --git a/src/test/checkqueue_tests.cpp b/src/test/checkqueue_tests.cpp index 153ccd984b..0d95bd7670 100644 --- a/src/test/checkqueue_tests.cpp +++ b/src/test/checkqueue_tests.cpp @@ -19,13 +19,17 @@ #include <vector> /** - * Identical to TestingSetup but excludes lock contention logging, as some of - * these tests are designed to be heavily contested to trigger race conditions - * or other issues. + * Identical to TestingSetup but excludes lock contention logging if + * `DEBUG_LOCKCONTENTION` is defined, as some of these tests are designed to be + * heavily contested to trigger race conditions or other issues. */ struct NoLockLoggingTestingSetup : public TestingSetup { NoLockLoggingTestingSetup() +#ifdef DEBUG_LOCKCONTENTION : TestingSetup{CBaseChainParams::MAIN, /*extra_args=*/{"-debugexclude=lock"}} {} +#else + : TestingSetup{CBaseChainParams::MAIN} {} +#endif }; BOOST_FIXTURE_TEST_SUITE(checkqueue_tests, NoLockLoggingTestingSetup) diff --git a/test/functional/rpc_misc.py b/test/functional/rpc_misc.py index 2f1796d7cc..f64aae7223 100755 --- a/test/functional/rpc_misc.py +++ b/test/functional/rpc_misc.py @@ -56,9 +56,6 @@ class RpcMiscTest(BitcoinTestFramework): self.log.info("test logging rpc and help") - # Test logging RPC returns the expected number of logging categories. - assert_equal(len(node.logging()), 27) - # Test toggling a logging category on/off/on with the logging RPC. assert_equal(node.logging()['qt'], True) node.logging(exclude=['qt']) |