#34775 kernel: allow only one global logging connection
| Reviewability | Reviews | Agreement | Size | ||||
|---|---|---|---|---|---|---|---|
| #34775 kernel: allow only one global logging connection | Ready | 0 | Mild | 132 + 96 tests | |||
|
|
|
| ||||
Reviewability: ReadyStalePaused Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs. Size: lines added or modified outside tests, then in tests; greener = smaller. | |||||||
Goal
Restricts libbitcoinkernel to a single process-wide logging connection, moves log level configuration onto the connection handle, and invokes logging callbacks without holding the logger mutex. Creating a second concurrent connection now fails, and logging callbacks can be invoked concurrently across threads.
Problem: The underlying KernelLogger is a process-wide singleton, but the API permitted multiple connection handles, misleading consumers into expecting independent loggers. In addition, holding the logger mutex while invoking the consumer callback serialized all logging threads on user code and risked deadlocks if the callback thread triggered any logging (such as during garbage collector finalization).
Evidence of importance:
- Description notes that multiple handles 'give the false impression of independent loggers.'
- Commit 921329000f notes that holding the lock 'serializes all logging threads on user code, and deadlocks if anything on the callback's thread logs, e.g. a garbage collector running finalizers that destroy kernel objects.'
Scope: Modifies the public libbitcoinkernel C API by renaming btck_logging_connection_create to btck_global_logging_connection_create, replacing btck_logging_set_min_level with btck_logging_connection_set_min_level, and requiring logging callbacks to be thread-safe.
Risk of a mistake: medium (other). Synchronization or concurrency bugs in the kernel logging interface could cause deadlocks, race conditions, or crashes in applications consuming libbitcoinkernel.
Changed since the previous assessment: Now invokes logging callbacks without holding the logger mutex, using an atomic in-flight counter to wait for running callbacks on connection destruction, and updates consumers like bitcoin-chainstate to format log output without interleaving concurrent lines.
Reviewability
Ready
Nothing known that would invalidate a review now.
Waiting on (from the thread read):
- reviewer: review of the updated approach and deadlock-free callback invocation 2026-10-19
Agreement
Mild
objection that needs a change was answered, no reply from the objector (ryanofsky: Prematurely restricts the kernel logging API in a way difficult to reverse without notable simplification)
Thread notes: The author updated the PR to invoke the logging callback without holding the logger mutex to avoid deadlocks from GC finalizers, restructured the commits, and marked the PR ready for review.
Objections, suggestions, and questions:
| Reviewer | Type | Harm, request, or question | Status | Must be | Author replied | Quote |
|---|---|---|---|---|---|---|
| purpleKarrot (member) | suggestion, interface | Drop local user_data in favor of a simple function pointer | answered · author replied that user_data avoids forcing users to use globals for state | answered | yes | 2026-03-09: 'Since the log function is global, there is no need for local user data. It can be a simple function pointer, even in the C++ wrapper.' Status from: 2026-03-09: stickies-v: 'Forcing the user to use globals if they need state seems unnecessary, when using `user_data` is I think a well-establish' |
| ryanofsky (member) | objection, approach | Prematurely restricts the kernel logging API in a way difficult to reverse without notable simplification | answered · author force-pushed to keep btck_LoggingConnection handles while enforcing a single active connection to avoid caller restructuring | changed | yes | 2026-03-09: 'I think it would be a mistake to limit functionality of the logging/debuging/tracing API prematurely, in a way that seems difficult to reverse and does not seem to provide a noticeable simplification' Status from: 2026-10-05: stickies-v: 'I believe this new approach addresses your concern about callers having to restructure if logging is contextualized late' |
| sedited (member) | question, maintenance | Does the pointer have to be a raw pointer? | answered · author explained that a raw pointer avoids running consumer code from static destructors during process teardown | answered | yes | 2026-06-11: 'Does this have to be a raw pointer?' Status from: 2026-09-16: stickies-v: 'I think so, to avoid running consumer code from static destructors.' |
| sedited (member) | objection, correctness | Global logging callback leaks state across unit tests if not reset | fixed · fix pushed · author pushed an RAII Logger class wrapper preventing state leakage across tests | changed | yes | 2026-06-11: 'Even though this function is scoped to this test, it now enables logging for all the the other unit tests too. Maybe add another call to set the callback to null at the end of the test?' Status from: 2026-09-17: stickies-v: 'The `Logger` class should offer all required functionality, in a way that is much harder to abuse. Thank you both for yo' |
| sedited (member) | suggestion, interface | Rename to logging_reset_callback and remove the argument | answered · author agreed in concept but noted it was rendered obsolete by the new Logger wrapper design | answered | yes | 2026-06-11: 'How about calling this `logging_reset_callback` and removing the argument?' Status from: 2026-09-17: stickies-v: 'I agree, but this is no longer relevant in the latest version as per https://github.com/bitcoin/bitcoin/pull/34775#discu' |
| w0xlt (contributor) | objection, correctness | Tests installing global callback leak state unless explicitly cleared | fixed · fix pushed · author adopted RAII wrapper approach to prevent test state leakage | changed | yes | 2026-07-16: 'any test that installs the global logging callback now needs to clear it before returning to prevent state leakage into later tests.' Status from: 2026-09-17: stickies-v: 'The `Logger` class should offer all required functionality, in a way that is much harder to abuse.' |
| w0xlt (contributor) | suggestion, interface | Retain RAII in the C++ wrapper while exposing a single global logging callback | fixed · fix pushed · author implemented an RAII Logger class in the C++ wrapper | answered | yes | 2026-07-16: 'I think the C++ wrapper could retain RAII while still exposing a single global logging callback.' Status from: 2026-09-17: stickies-v: 'address @w0xlt's suggestion to have an RAII `Logger` in the C++ wrapper instead of free functions' |
Support:
- sedited (member) (Concept ACK, 2026-03-09) [read]: Not having separate connections seems simpler, clients can multiplex themselves, and it is pragmatic
- w0xlt (contributor) (Approach ACK, 2026-06-24): (no reason given) [not substantive]
Participants:
- purpleKarrot (member, neutral, 1 statements 2026-03-09 to 2026-03-09): suggested dropping user_data in favor of a plain function pointer
- ryanofsky (member, objection, 2 statements 2026-03-09 to 2026-09-25): objected that limiting logging API to a global callback is premature, hard to reverse, and disrupts callers
- sedited (member, support, 6 statements 2026-03-09 to 2026-08-27): Concept ACK; raised concern about test state leakage and asked about raw pointer
- w0xlt (contributor, support, 3 statements 2026-06-24 to 2026-07-16): Approach ACK; noted test callback leakage and suggested RAII wrapper
Files
114 lines under test/bench/ci.
- src/kernel/bitcoinkernel.cpp +87/-62
- src/test/kernel/test_kernel.cpp +96/-18
- src/kernel/bitcoinkernel.h +27/-22
- src/kernel/bitcoinkernel_wrapper.h +9/-6
- src/bitcoin-chainstate.cpp +9/-4
Card
The short text the ranking pass compares across PRs.
Restricts libbitcoinkernel to allow only one active logging connection per process, and executes logging callbacks without holding the logger mutex. Previously, multiple connection handles gave consumers the false impression of independent loggers, while holding the mutex serialized all logging threads and risked deadlocks if consumer callbacks triggered kernel logging. Attempting to create a second connection now fails, log level configuration is moved to the connection handle, and callbacks must be thread-safe as they can run concurrently.
Data
thread read through 2026-10-19 (20 statements), head 921329000f
labels: Validation
Categories
Kernel (libbitcoinkernel)
P1 · bug fix (assessed alone as P2; Raised to P1 and moved up five places: a deadlock risk when consumer callbacks log is a reliability defect exactly at the kernel boundary, and the single-connection decision also gates the per-context logging series.)
Fixes a potential deadlock at the kernel boundary by releasing the logger mutex before invoking consumer callbacks, and aligns the API with the underlying singleton logger. As noted in commit 921329000f, holding the lock 'serializes all logging threads on user code, and deadlocks if anything on the callback's thread logs, e.g. a garbage collector running finalizers that destroy kernel objects.'
Membership: Modifies the libbitcoinkernel C/C++ API headers and implementations (`src/kernel/bitcoinkernel.h`, `src/kernel/bitcoinkernel.cpp`), kernel tests, and the `bitcoin-chainstate` example.
Factors: security/stability 2, bug 1, performance 1, user value 1, leverage 1