feat: make logging machinery thread safe#3050
Conversation
|
How does this relate to #2840? That one also claims to make logging threadsafe but is a 1-liner and has tests. |
ivand's PR is much simpler but:
We don't need to protect every logging function with a guard for #2954. Just the file sink + log write. So we could eg. remove the guard setMinLevel(). But again, this adds proper thread safety across the board.
tests are a good idea. |
Add three Catch2 cases to TestILog.cpp that stress the logging machinery concurrently: - ConcurrentRecordDispatch: N threads flooding records at mixed levels/sections - ConcurrentSinkRegistryChurn: writers logging while a mutator churns the shared logFiles - ConcurrentFilterChanges: writers logging on a section while another thread changes its filter level and re-registers it Wire ThreadSanitizer: - new USE_TSAN CMake option (whole-engine TSan). Similar to USE_ASAN. - test_ILog is built with -fsanitize=thread by default on Linux so the cases can be run with `./test/test_ILog "[multithreaded]"` without a separate build tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
a37b20e to
a78fea0
Compare
|
added tests in a new commit. If we have a desire to simplify this we'd need to:
|
|
My main useful feedback is that AFAIK the current design for logging thread-safety is supposed to make For reviewing the actual thread-safety it would probably best for @lostsquirrel1 to look. |
|
I'm no expert here, but have you considered instead of applying mutex, I was thinking maybe a thread-safe queue that will buffer logs. Then a log writer on the main thread that will read from the queue and actually do the file writes. Wouldn't that make it thread safe logging without having mutexes all over the place? |
yes what you're describing is async logging, where one thread owns the actual writes and other threads just append to a concurrent queue. Genuine tradeoff there in different kind of complexity (you have to then deal with: what happens during a crash because you probably need to flush/print fatal logs synchronously, what happens if loggers add so many logs the queue outpaces how fast the writer thread can write, etc.). But that could be preferable to just tacking on a bunch of concurrency complexity onto the existing logger in-discord discussion here: https://discord.com/channels/549281623154229250/724924957074915358/1518918926069928088 |
Current logging machinery is only threadsafe because all init is done single-threaded at startup, and threads ONLY collide on the POSIX
fprintf(which locks internally).With #2954, init machinery can now run at any time, so we need to guard logger callsites.
This would be very easy, except there's some complexity with thread freezing to print stacktraces since the thread could be holding the lock while frozen.
I ran some basic testing in running scenarios/skirmish in both headful and headless and everything seemed fine.
AI Disclosure
My fingers/brain + Claude Code for some finer details