diff --git a/shell/browser/api/electron_api_power_monitor_win.cc b/shell/browser/api/electron_api_power_monitor_win.cc index 9c223dcaf7..6267699e72 100644 --- a/shell/browser/api/electron_api_power_monitor_win.cc +++ b/shell/browser/api/electron_api_power_monitor_win.cc @@ -7,9 +7,14 @@ #include #include +#include "base/debug/alias.h" +#include "base/debug/crash_logging.h" #include "base/logging.h" +#include "base/strings/string_number_conversions.h" +#include "base/win/windows_handle_util.h" #include "base/win/windows_types.h" #include "base/win/wrapped_window_proc.h" +#include "components/crash/core/common/crash_key.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "ui/gfx/win/hwnd_util.h" @@ -20,6 +25,18 @@ namespace { const wchar_t kPowerMonitorWindowClass[] = L"Electron_PowerMonitorHostWindow"; +std::string DescribeMemoryState(void* address) { + MEMORY_BASIC_INFORMATION mbi = {}; + if (!VirtualQuery(address, &mbi, sizeof(mbi))) { + return "VirtualQuery failed err=" + base::NumberToString(::GetLastError()); + } + // Refs + // https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-memory_basic_information + return "state=" + base::NumberToString(mbi.State) + + " protect=" + base::NumberToString(mbi.Protect) + + " type=" + base::NumberToString(mbi.Type); +} + } // namespace namespace api { @@ -49,12 +66,35 @@ void PowerMonitor::InitPlatformSpecificMonitors() { static_cast(window_), DEVICE_NOTIFY_WINDOW_HANDLE); PLOG_IF(ERROR, !power_notify_handle_) << "RegisterSuspendResumeNotification failed"; + + // On ARM64 Windows, UnregisterSuspendResumeNotification may + // crash in powrprof!PowerUnregisterSuspendResumeNotification by dereferencing + // the HPOWERNOTIFY handle. VirtualQuery on the handle address reveals + // whether it was ever a valid pointer. + // Use static crash keys (not SCOPED_) so they persist until the crash. + if (power_notify_handle_) { + static crash_reporter::CrashKeyString<16> reg_handle_key("pm-reg-handle"); + static crash_reporter::CrashKeyString<64> reg_memstate_key( + "pm-reg-memstate"); + reg_handle_key.Set( + base::NumberToString(base::win::HandleToUint32(power_notify_handle_))); + reg_memstate_key.Set(DescribeMemoryState(power_notify_handle_)); + } } void PowerMonitor::DestroyPlatformSpecificMonitors() { if (window_) { WTSUnRegisterSessionNotification(window_); if (power_notify_handle_) { + // Capture handle value and memory state at unregistration time. + // debug::Alias forces the raw value onto the stack. + auto handle_value = base::win::HandleToUint32(power_notify_handle_); + base::debug::Alias(&handle_value); + + static crash_reporter::CrashKeyString<64> unreg_memstate_key( + "pm-unreg-memstate"); + unreg_memstate_key.Set(DescribeMemoryState(power_notify_handle_)); + UnregisterSuspendResumeNotification(power_notify_handle_); power_notify_handle_ = nullptr; }