Chromium Code Reviews| Index: components/crash/content/app/fallback_crash_handling_win.cc |
| diff --git a/components/crash/content/app/fallback_crash_handling_win.cc b/components/crash/content/app/fallback_crash_handling_win.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..e83be6275ea77ffa663600dbd8e9586d08ff36b4 |
| --- /dev/null |
| +++ b/components/crash/content/app/fallback_crash_handling_win.cc |
| @@ -0,0 +1,119 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "components/crash/content/app/fallback_crash_handling_win.h" |
| + |
| +#include <memory> |
| + |
| +#include "base/base_switches.h" |
| +#include "base/command_line.h" |
| +#include "base/logging.h" |
| +#include "components/crash/content/app/crash_switches.h" |
| +#include "components/crash/content/app/fallback_crash_handler_launcher_win.h" |
| +#include "components/crash/content/app/fallback_crash_handler_win.h" |
| + |
| +namespace crash_reporter { |
| + |
| +namespace switches { |
| +const char kFallbackCrashHandler[] = "fallback-handler"; |
| +const char kPrefetchArgument[] = "/prefetch:7"; |
| +} |
| + |
| +const uint32_t kFallbackCrashTerminationCode = 0xFFFF8001; |
| + |
| +namespace { |
| + |
| +std::unique_ptr<FallbackCrashHandlerLauncher> g_fallback_crash_handler_launcher; |
|
brucedawson
2017/01/26 19:43:21
Why are we using a global variable with a construc
Sigurður Ásgeirsson
2017/08/25 20:20:55
Done.
|
| + |
| +LONG WINAPI FallbackUnhandledExceptionFilter(EXCEPTION_POINTERS* exc_ptrs) { |
| + if (!g_fallback_crash_handler_launcher) |
| + return EXCEPTION_CONTINUE_SEARCH; |
| + |
| + return g_fallback_crash_handler_launcher->LaunchAndWaitForHandler(exc_ptrs); |
| +} |
| + |
| +} // namespace |
| + |
| +bool SetupFallbackCrashHandling(const base::CommandLine& command_line) { |
| + DCHECK(!g_fallback_crash_handler_launcher); |
| + |
| + // Run the same program. |
| + base::CommandLine base_command_line(command_line.GetProgram()); |
| + base_command_line.AppendSwitchASCII("type", switches::kFallbackCrashHandler); |
| + |
| + // This is to support testing under gtest. |
| + if (command_line.HasSwitch(::switches::kTestChildProcess)) { |
| + base_command_line.AppendSwitchASCII( |
| + ::switches::kTestChildProcess, |
| + command_line.GetSwitchValueASCII(::switches::kTestChildProcess)); |
| + } |
| + |
| + // All Chrome processes need a prefetch argument. |
| + base_command_line.AppendArg(switches::kPrefetchArgument); |
| + |
| + // Get the database path. |
| + base::FilePath database_path = command_line.GetSwitchValuePath("database"); |
| + if (database_path.empty()) { |
| + NOTREACHED(); |
| + return false; |
| + } |
| + |
| + std::unique_ptr<FallbackCrashHandlerLauncher> fallback_launcher( |
| + new FallbackCrashHandlerLauncher()); |
| + |
| + if (!fallback_launcher->Initialize(base_command_line, database_path)) { |
| + NOTREACHED(); |
| + return false; |
| + } |
| + |
| + // This is necessary because chrome_elf stubs out the |
| + // SetUnhandledExceptionFilter in the IAT of chrome.exe. |
| + typedef PTOP_LEVEL_EXCEPTION_FILTER(WINAPI * |
| + SetUnhandledExceptionFilterFunction)( |
| + PTOP_LEVEL_EXCEPTION_FILTER filter); |
| + HMODULE kernel32 = GetModuleHandle(L"kernel32.dll"); |
| + if (!kernel32) |
| + return false; |
| + |
| + SetUnhandledExceptionFilterFunction set_unhandled_exception_filter = |
| + reinterpret_cast<SetUnhandledExceptionFilterFunction>( |
| + GetProcAddress(kernel32, "SetUnhandledExceptionFilter")); |
| + if (!set_unhandled_exception_filter) |
| + return false; |
| + |
| + // Success, pass ownership to the global. |
| + g_fallback_crash_handler_launcher = std::move(fallback_launcher); |
| + |
| + set_unhandled_exception_filter(&FallbackUnhandledExceptionFilter); |
| + |
| + return true; |
| +} |
| + |
| +int RunAsFallbackCrashHandler(const base::CommandLine& command_line, |
| + std::string product_name, |
| + std::string version, |
| + std::string channel_name) { |
| + FallbackCrashHandler fallback_handler; |
| + |
| + if (!fallback_handler.ParseCommandLine(command_line)) { |
| + // TODO(siggi): Figure out how to UMA from this process, if need be. |
| + return 1; |
| + } |
| + |
| + if (!fallback_handler.GenerateCrashDump( |
| + product_name, version, channel_name, |
| + crash_reporter::switches::kCrashpadHandler)) { |
| + // TODO(siggi): Figure out how to UMA from this process, if need be. |
| + return 2; |
| + } |
| + |
| + if (!fallback_handler.process().Terminate(kFallbackCrashTerminationCode, |
| + false)) { |
| + return 3; |
| + } |
| + |
| + return 0; |
| +} |
| + |
| +} // namespace crash_reporter |