Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "components/crash/content/app/fallback_crash_handling_win.h" | |
| 6 | |
| 7 #include <memory> | |
| 8 | |
| 9 #include "base/base_switches.h" | |
| 10 #include "base/command_line.h" | |
| 11 #include "base/logging.h" | |
| 12 #include "components/crash/content/app/crash_switches.h" | |
| 13 #include "components/crash/content/app/fallback_crash_handler_launcher_win.h" | |
| 14 #include "components/crash/content/app/fallback_crash_handler_win.h" | |
| 15 | |
| 16 namespace crash_reporter { | |
| 17 | |
| 18 namespace switches { | |
| 19 const char kFallbackCrashHandler[] = "fallback-handler"; | |
| 20 const char kPrefetchArgument[] = "/prefetch:7"; | |
| 21 } | |
| 22 | |
| 23 const uint32_t kFallbackCrashTerminationCode = 0xFFFF8001; | |
| 24 | |
| 25 namespace { | |
| 26 | |
| 27 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.
| |
| 28 | |
| 29 LONG WINAPI FallbackUnhandledExceptionFilter(EXCEPTION_POINTERS* exc_ptrs) { | |
| 30 if (!g_fallback_crash_handler_launcher) | |
| 31 return EXCEPTION_CONTINUE_SEARCH; | |
| 32 | |
| 33 return g_fallback_crash_handler_launcher->LaunchAndWaitForHandler(exc_ptrs); | |
| 34 } | |
| 35 | |
| 36 } // namespace | |
| 37 | |
| 38 bool SetupFallbackCrashHandling(const base::CommandLine& command_line) { | |
| 39 DCHECK(!g_fallback_crash_handler_launcher); | |
| 40 | |
| 41 // Run the same program. | |
| 42 base::CommandLine base_command_line(command_line.GetProgram()); | |
| 43 base_command_line.AppendSwitchASCII("type", switches::kFallbackCrashHandler); | |
| 44 | |
| 45 // This is to support testing under gtest. | |
| 46 if (command_line.HasSwitch(::switches::kTestChildProcess)) { | |
| 47 base_command_line.AppendSwitchASCII( | |
| 48 ::switches::kTestChildProcess, | |
| 49 command_line.GetSwitchValueASCII(::switches::kTestChildProcess)); | |
| 50 } | |
| 51 | |
| 52 // All Chrome processes need a prefetch argument. | |
| 53 base_command_line.AppendArg(switches::kPrefetchArgument); | |
| 54 | |
| 55 // Get the database path. | |
| 56 base::FilePath database_path = command_line.GetSwitchValuePath("database"); | |
| 57 if (database_path.empty()) { | |
| 58 NOTREACHED(); | |
| 59 return false; | |
| 60 } | |
| 61 | |
| 62 std::unique_ptr<FallbackCrashHandlerLauncher> fallback_launcher( | |
| 63 new FallbackCrashHandlerLauncher()); | |
| 64 | |
| 65 if (!fallback_launcher->Initialize(base_command_line, database_path)) { | |
| 66 NOTREACHED(); | |
| 67 return false; | |
| 68 } | |
| 69 | |
| 70 // This is necessary because chrome_elf stubs out the | |
| 71 // SetUnhandledExceptionFilter in the IAT of chrome.exe. | |
| 72 typedef PTOP_LEVEL_EXCEPTION_FILTER(WINAPI * | |
| 73 SetUnhandledExceptionFilterFunction)( | |
| 74 PTOP_LEVEL_EXCEPTION_FILTER filter); | |
| 75 HMODULE kernel32 = GetModuleHandle(L"kernel32.dll"); | |
| 76 if (!kernel32) | |
| 77 return false; | |
| 78 | |
| 79 SetUnhandledExceptionFilterFunction set_unhandled_exception_filter = | |
| 80 reinterpret_cast<SetUnhandledExceptionFilterFunction>( | |
| 81 GetProcAddress(kernel32, "SetUnhandledExceptionFilter")); | |
| 82 if (!set_unhandled_exception_filter) | |
| 83 return false; | |
| 84 | |
| 85 // Success, pass ownership to the global. | |
| 86 g_fallback_crash_handler_launcher = std::move(fallback_launcher); | |
| 87 | |
| 88 set_unhandled_exception_filter(&FallbackUnhandledExceptionFilter); | |
| 89 | |
| 90 return true; | |
| 91 } | |
| 92 | |
| 93 int RunAsFallbackCrashHandler(const base::CommandLine& command_line, | |
| 94 std::string product_name, | |
| 95 std::string version, | |
| 96 std::string channel_name) { | |
| 97 FallbackCrashHandler fallback_handler; | |
| 98 | |
| 99 if (!fallback_handler.ParseCommandLine(command_line)) { | |
| 100 // TODO(siggi): Figure out how to UMA from this process, if need be. | |
| 101 return 1; | |
| 102 } | |
| 103 | |
| 104 if (!fallback_handler.GenerateCrashDump( | |
| 105 product_name, version, channel_name, | |
| 106 crash_reporter::switches::kCrashpadHandler)) { | |
| 107 // TODO(siggi): Figure out how to UMA from this process, if need be. | |
| 108 return 2; | |
| 109 } | |
| 110 | |
| 111 if (!fallback_handler.process().Terminate(kFallbackCrashTerminationCode, | |
| 112 false)) { | |
| 113 return 3; | |
| 114 } | |
| 115 | |
| 116 return 0; | |
| 117 } | |
| 118 | |
| 119 } // namespace crash_reporter | |
| OLD | NEW |