TrueHUD
TrueHUD copied to clipboard
Fix std::bad_function_call crash and eliminate HUD task queue data race; add tests, CI, and DX improvements
Summary
Fixes a critical std::bad_function_call crash in HUD task processing and improves thread-safety across the task queue system. Also adds unit tests, Windows CI workflow, and build system improvements.
Problem
Users reported crashes when Actor Info Bars or Boss Bars are enabled, particularly with follower frameworks:
- Exception:
std::bad_function_callinTrueHUD.dll - Cause: Task queue accessed concurrently from multiple threads without synchronization, leading to empty or corrupted
std::functionobjects
Solution
Core Fix: Thread-Safe Task Processing
Implemented drain-and-process pattern for both HUDHandler and WidgetBase:
- Drain under lock: Swap entire queue into local storage under mutex
- Process outside lock: Execute tasks without holding mutex, preventing deadlocks and contention
- Guard invocation: Check
std::functionvalidity before calling to prevent crashes
// New pattern in HUDHandler::Process and WidgetBase::ProcessDelegates
std::queue<Task> localTasks;
{
Locker locker(_lock);
std::swap(localTasks, _taskQueue);
}
while (!localTasks.empty()) {
auto task = std::move(localTasks.front());
localTasks.pop();
if (task) { // Guard against empty functions
task();
}
}
Additional Fixes
- Menu visibility handling: Refactored to avoid
ControlMap::contextPriorityStackcrashes; now uses direct menu state checks - Null checks: Added safety guards for
ObjectRefHandle::get()results before dereferencing - Build system: Default
CompiledPluginsPath, allowSKSE_SUPPORT_XBYAKoverride, ensure deploy directory exists
Testing
- Unit tests added (Catch2) validating:
- Empty task handling without crashes
- FIFO ordering within drained batches
- Reentrancy (tasks added during processing run next cycle)
- Concurrent producer/consumer scenarios
- CI workflow (Windows): Build Debug + run tests on every push
- Manual testing performed within large modlists that use TrueHUD to confirm functionality.
Files Changed
Core (thread-safety fixes):
src/HUDHandler.cpp|.h- Drain-and-process pattern, menu visibility refactorsrc/TrueHUDAPI.h- Same pattern forWidgetBase::ProcessDelegatessrc/Widgets/InfoBarBase.cpp- Null check improvementssrc/main.cpp- ConditionalREL::Module::reset()for test builds
Build/Infrastructure:
CMakeLists.txt,src/CMakeLists.txt- Build system improvementsvcpkg.json- Add Catch2 dependency.gitignore- Simplify patterns
Tests:
tests/widgetbase_tests.cpp- WidgetBase delegate processing teststests/hudhandler_process_tests.cpp- HUDHandler task queue tests
CI:
.github/workflows/ci.yml- Windows build + test automation
Backward Compatibility
No breaking changes to TrueHUD API or existing functionality.