Skip to content

Hold m_loggersMutex in LoggerSystem::Shutdown#146

Open
JustinMDotNet wants to merge 1 commit into
wopss:masterfrom
JustinMDotNet:fix/logger-system-shutdown-lock
Open

Hold m_loggersMutex in LoggerSystem::Shutdown#146
JustinMDotNet wants to merge 1 commit into
wopss:masterfrom
JustinMDotNet:fix/logger-system-shutdown-lock

Conversation

@JustinMDotNet

Copy link
Copy Markdown

Closes #139.

What this changes

LoggerSystem::Shutdown now takes m_loggersMutex before iterating m_loggers and calling clear(). One line added at the top of the function.

Why

Log<T> in LoggerSystem.hpp:51-73 already locks the mutex for the lookup/emplace. Shutdown was the only path that mutated the same map without the lock, so any plugin thread or in-flight hook callback that called Log during shutdown could:

  • emplace into the map while Shutdown was mid-iteration (iterator invalidation), or
  • read from the map after clear() had run.

The window is narrow but real: the reverse-order shutdown in App::Shutdown runs LoggerSystem::Shutdown last, by which point plugins have been "unloaded" but RED4ext's own game-side detours are still patched (those are not removed until App::Destruct, see #141). Anything those detours route into that calls back through the logger races against the clear.

What I tested

Local rebuild. Functional behavior is unchanged on the single-threaded path; the only effect is that concurrent calls to Log during shutdown now serialize correctly instead of racing on the underlying unordered_map.

Note

This is companion to #141. Even after this PR, the safest fix for the shutdown story is to detach RED4ext's own hooks before any system is shut down, which is what #141 proposes separately. This PR fixes the lock-discipline bug in isolation; the two PRs are independent.

Log<T> already takes m_loggersMutex around the lookup/emplace into
m_loggers, but Shutdown iterated and cleared the same map with no
lock. Any plugin thread or in-flight hook callback that called Log
during shutdown could race against the iteration or use-after-clear.

The race window is small but not theoretical: in the reverse-order
shutdown, LoggerSystem::Shutdown runs last while RED4ext's own
detours are still attached (those are detached in App::Destruct, see
issue wopss#141).

Take the scoped_lock at the top of Shutdown so the flush + clear
pair is atomic with respect to Log.

Fixes wopss#139

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

LoggerSystem::Shutdown clears m_loggers without holding m_loggersMutex

2 participants