Problem: A kernel application whose log callback logs, or destroys a kernel object, hangs. The common way to hit this is a garbage-collected language binding: Python's garbage collector can run finalizers inside the callback, and a finalizer that destroys a chainstate manager flushes and logs (https://github.com/bitcoin/bitcoin/pull/34775#issuecomment-6278257737, #34374 (review)). The cause is that the kernel calls log callbacks while holding the logger's mutex, so any logging from inside a callback blocks on a mutex its own thread already holds.
Solution: This PR calls log callbacks without holding the mutex. The kernel API is unchanged, including support for multiple logging connections.
This is an alternative to the last commit of #34775, which fixes the same deadlock but only after limiting the process to one logging connection. Fixing the deadlock separately lets it merge without waiting on that API question. If #34775 is going to merge soon with its own fix, this PR can be closed.
Behavior changes for callers:
- Callbacks can run on several threads at the same time, so they must be thread-safe. Entries from different threads arrive in no particular order.
- A callback can log, and can create or destroy kernel objects and other logging connections. Destroying a callback's own connection from inside it aborts instead of hanging.
The change is in src/kernel/bitcoinkernel.cpp (about 45 lines) plus header docs and new test_kernel cases, which hang without the fix. Details are in the commit message.