Compare commits

...

2 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
2792f07da0 Fix mutex inconsistency in HotkeyConflictManager - use recursive_mutex and guard all public methods
Agent-Logs-Url: https://github.com/microsoft/PowerToys/sessions/9787d35f-073e-45ca-b065-5dadede49cd7

Co-authored-by: MuyuanMS <116717757+MuyuanMS@users.noreply.github.com>
2026-04-29 08:51:40 +00:00
copilot-swe-agent[bot]
61772a5a0c Initial plan 2026-04-29 08:48:54 +00:00
2 changed files with 10 additions and 3 deletions

View File

@@ -36,6 +36,7 @@ namespace HotkeyConflictDetector
HotkeyConflictType HotkeyConflictManager::HasConflict(Hotkey const& _hotkey, const wchar_t* _moduleName, const int _hotkeyID)
{
std::lock_guard<std::recursive_mutex> lock(hotkeyMutex);
if (disabledHotkeys.find(_moduleName) != disabledHotkeys.end())
{
return HotkeyConflictType::NoConflict;
@@ -79,6 +80,7 @@ namespace HotkeyConflictDetector
HotkeyConflictType HotkeyConflictManager::HasConflict(Hotkey const& _hotkey)
{
std::lock_guard<std::recursive_mutex> lock(hotkeyMutex);
uint16_t handle = GetHotkeyHandle(_hotkey);
if (handle == 0)
@@ -113,6 +115,7 @@ namespace HotkeyConflictDetector
// It returns a list of all conflicting shortcuts.
std::vector<HotkeyConflictInfo> HotkeyConflictManager::GetAllConflicts(Hotkey const& _hotkey)
{
std::lock_guard<std::recursive_mutex> lock(hotkeyMutex);
std::vector<HotkeyConflictInfo> conflicts;
uint16_t handle = GetHotkeyHandle(_hotkey);
@@ -164,6 +167,7 @@ namespace HotkeyConflictDetector
bool HotkeyConflictManager::AddHotkey(Hotkey const& _hotkey, const wchar_t* _moduleName, const int _hotkeyID, bool isEnabled)
{
std::lock_guard<std::recursive_mutex> lock(hotkeyMutex);
if (!isEnabled)
{
disabledHotkeys[_moduleName].push_back({ _hotkey, _moduleName, _hotkeyID });
@@ -211,12 +215,13 @@ namespace HotkeyConflictDetector
{
std::vector<HotkeyConflictInfo> removedHotkeys;
std::lock_guard<std::recursive_mutex> lock(hotkeyMutex);
if (disabledHotkeys.find(moduleName) != disabledHotkeys.end())
{
disabledHotkeys.erase(moduleName);
}
std::lock_guard<std::mutex> lock(hotkeyMutex);
bool foundRecord = false;
for (auto it = sysConflictHotkeyMap.begin(); it != sysConflictHotkeyMap.end();)
@@ -310,6 +315,7 @@ namespace HotkeyConflictDetector
void HotkeyConflictManager::EnableHotkeyByModule(const std::wstring& moduleName)
{
std::lock_guard<std::recursive_mutex> lock(hotkeyMutex);
if (disabledHotkeys.find(moduleName) == disabledHotkeys.end())
{
return; // No disabled hotkeys for this module
@@ -327,6 +333,7 @@ namespace HotkeyConflictDetector
void HotkeyConflictManager::DisableHotkeyByModule(const std::wstring& moduleName)
{
std::lock_guard<std::recursive_mutex> lock(hotkeyMutex);
auto hotkeys = RemoveHotkeyByModule(moduleName);
disabledHotkeys[moduleName] = hotkeys;
}
@@ -382,7 +389,7 @@ namespace HotkeyConflictDetector
json::JsonObject HotkeyConflictManager::GetHotkeyConflictsAsJson()
{
std::lock_guard<std::mutex> lock(hotkeyMutex);
std::lock_guard<std::recursive_mutex> lock(hotkeyMutex);
using namespace json;
JsonObject root;

View File

@@ -57,7 +57,7 @@ namespace HotkeyConflictDetector
static std::mutex instanceMutex;
static HotkeyConflictManager* instance;
std::mutex hotkeyMutex;
std::recursive_mutex hotkeyMutex;
// Hotkey in hotkeyMap means the hotkey has been registered successfully
std::unordered_map<uint16_t, HotkeyConflictInfo> hotkeyMap;
// Hotkey in sysConflictHotkeyMap means the hotkey has conflict with system defined hotkeys