Repository navigation
Fix data races in monitor thread, restore-on-exit, add features + tests - #1
Merged
Merged
Conversation
Thread-safety (fixes crashes / use-after-free): - UI thread now publishes an immutable profile snapshot that the monitor thread reads, instead of both threads mutating the live g_Profiles vector. - Replace the dangling AppProfile* g_ActiveProfile with a value copy plus an atomic index, so vector reallocation can no longer invalidate it. - Serialize all active-state (original dev mode, changed flag, index) behind g_RestoreMutex; make g_ProcessFoundTime/g_ActiveIndex atomic. Reliability: - Restore the original resolution when the app exits and on WM_ENDSESSION (logoff/shutdown) if a profile change is active. - Test Display Settings now auto-reverts after 15s via a timer instead of a blocking MessageBox, so an unreadable mode can always be recovered. - Single-instance mutex prevents duplicate tray icons / competing monitors. - Atomic config save (temp file + MoveFileEx) avoids corruption on crash. - IsProcessRunning handles an invalid toolhelp snapshot. UX / correctness: - Validate Width/Height before save and test; clamp Hz/Delay to >= 0. - Load the tray/window icon at the proper size via LoadImage and free it. - Fix signed/unsigned comparisons; handle GetMessage error and join safely. - Build clean with -Wall -Wextra -Wpedantic. Docs/build: - README updated for timed test revert and guaranteed restoration. - Add .gitignore; document the hardened build command.
UI / UX: - Add a live 'Supported Modes' dropdown populated from EnumDisplaySettings for the selected monitor, so listed modes are guaranteed to be supported. - Owner-draw profile list showing each target app's extracted icon. - Drag-and-drop an .exe onto the window to fill the executable path. - Dark mode toggle (immersive dark title bar + WM_CTLCOLOR* themed controls). - Optional diagnostic logging to %APPDATA%\AutoResChanger\log.txt. - Tray menu gains 'Restore resolution now' and 'Open config folder'. Robustness / performance: - Single-pass process enumeration per tick (set-based) instead of one snapshot per profile; adaptive 1s/2s polling with interruptible sleep. - Handle WM_DISPLAYCHANGE to re-enumerate monitors and refresh modes. - Per-monitor-v2 DPI awareness with graceful fallbacks. - Persist dark-mode/logging prefs; free theme brushes, icons and handles. Build / docs: - Add CMakeLists.txt (MinGW + MSVC) and a PowerShell build.ps1. - Add GitHub Actions workflow that builds and attaches the exe to releases. - README updated for all new features and build options.
…tatus UX (non-blocking feedback): - Replace all MessageBox validation pop-ups (Save/Test/drag-drop) with an inline status line that colour-codes info/warn/error/ok and auto-clears. This keeps the UI responsive and makes the flows fully automatable. - Rework Test into a two-phase flow: apply the mode and arm a 15s countdown; the button becomes 'Keep This Mode' to confirm, otherwise it auto-reverts. Fixes the previous behaviour where the blocking OK box cancelled the timer immediately, so it never actually auto-reverted. - Assign control IDs to the exe/Hz/Delay/restore/enable fields for testability. Testing: - tests/test_main.cpp: headless unit tests (36 checks) compiled with -DTESTING, which excludes the GUI. Covers GetFileName, ToLowerCopy, config save/load round-trip, atomic-write cleanliness, overwrite semantics, EnumModesForDevice, GetCurrentRes, process enumeration, and missing-config. - tests/gui_save_test.ps1: drives the real window via Win32 messages to verify the Save/Delete/validation end-to-end flow and config output. Uses WM_SETTEXT (marshaled cross-process) so inputs reach the owning process correctly. - tests/run_tests.ps1: one-shot builder/runner for both suites. - CMakeLists.txt gains a ctest target; CI workflow builds and runs all tests. main.cpp is unchanged in behaviour except the dialog/status refactor; the GUI is now guarded by #ifndef TESTING so the same source backs the tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The monitor thread shared mutable state with the UI thread, which could crash. Fixed that plus a few other bugs, added the features I wanted, and wrote tests.
Bugs fixed
g_Profiles— the worker iterated the vector while the UI thread resized it. Now the UI thread hands the worker an immutable snapshot.g_ActiveProfilepointed into the vector and went stale on reallocation. Now it's a value copy plus an index.Safety
Features
%APPDATA%.WM_DISPLAYCHANGE, per-monitor-v2 DPI, faster adaptive process polling.Tests
tests/test_main.cpp, 36 checks): config round-trip, atomic write, mode enumeration, process detection, path parsing.tests/gui_save_test.ps1): drives the real window and checks Save/Delete/validation produce the right config.Builds clean with
-Wall -Wextra -Wpedantic. 36/36 unit tests, 3/3 GUI tests pass.