diff --git a/components/crashcatcher/windows_crashmonitor.cpp b/components/crashcatcher/windows_crashmonitor.cpp index 2c942e00b7..4627380356 100644 --- a/components/crashcatcher/windows_crashmonitor.cpp +++ b/components/crashcatcher/windows_crashmonitor.cpp @@ -18,6 +18,7 @@ namespace Crash { + std::unordered_map CrashMonitor::smEventHookOwners{}; CrashMonitor::CrashMonitor(HANDLE shmHandle) : mShmHandle(shmHandle) @@ -85,6 +86,10 @@ namespace Crash bool CrashMonitor::isAppFrozen() { + MSG message; + // Allow the event hook callback to run + PeekMessage(&message, nullptr, 0, 0, PM_NOREMOVE); + if (!mAppWindowHandle) { EnumWindows([](HWND handle, LPARAM param) -> BOOL { @@ -102,7 +107,20 @@ namespace Crash }, (LPARAM)this); if (mAppWindowHandle) { - // TODO: use https://devblogs.microsoft.com/oldnewthing/20111026-00/?p=9263 to monitor for the window being destroyed + DWORD processId; + GetWindowThreadProcessId(mAppWindowHandle, &processId); + HWINEVENTHOOK eventHookHandle = SetWinEventHook(EVENT_OBJECT_DESTROY, EVENT_OBJECT_DESTROY, nullptr, + [](HWINEVENTHOOK hWinEventHook, DWORD event, HWND windowHandle, LONG objectId, LONG childId, DWORD eventThread, DWORD eventTime) + { + CrashMonitor& crashMonitor = *smEventHookOwners[hWinEventHook]; + if (event == EVENT_OBJECT_DESTROY && windowHandle == crashMonitor.mAppWindowHandle && objectId == OBJID_WINDOW && childId == INDEXID_CONTAINER) + { + crashMonitor.mAppWindowHandle = nullptr; + smEventHookOwners.erase(hWinEventHook); + UnhookWinEvent(hWinEventHook); + } + }, processId, mAppMainThreadId, WINEVENT_OUTOFCONTEXT); + smEventHookOwners[eventHookHandle] = this; } else return false; diff --git a/components/crashcatcher/windows_crashmonitor.hpp b/components/crashcatcher/windows_crashmonitor.hpp index 01acd34bdd..031e5b0612 100644 --- a/components/crashcatcher/windows_crashmonitor.hpp +++ b/components/crashcatcher/windows_crashmonitor.hpp @@ -33,6 +33,8 @@ private: HANDLE mShmHandle = nullptr; HANDLE mShmMutex = nullptr; + static std::unordered_map smEventHookOwners; + void signalApp() const; bool waitApp() const;