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. The problem is not new and has existed since logging callbacks were introduced in #30595.
Solution: This PR delivers log entries through btcsignals::signal, which calls callbacks without holding any lock, replacing the kernel's own callback list and custom dispatching mechanism.
The change is a usability improvement and a bugfix because with it applications no longer need to reason about deadlocks and blocking behavior from a mutex they can't see. However, they may need to be updated to deal with log callbacks that are no longer serialized and connection functions that no longer block. Compatibility details are in the commit message.
The main code change is in src/kernel/bitcoinkernel.cpp (+42/-77) accompanied by header docs and new test_kernel cases, which hang without the fix. There is also a commit switching btcsignals.h to use StdMutex instead of Mutex so it is safe to use in logging callbacks.
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, and still hangs if a callback destroys the connection.