Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | ============== |
michael@0 | 2 | Crash Reporter |
michael@0 | 3 | ============== |
michael@0 | 4 | |
michael@0 | 5 | Overview |
michael@0 | 6 | ======== |
michael@0 | 7 | |
michael@0 | 8 | The **crash reporter** is a subsystem to record and manage application |
michael@0 | 9 | crash data. |
michael@0 | 10 | |
michael@0 | 11 | While the subsystem is known as *crash reporter*, it helps to think of |
michael@0 | 12 | it more as a *process dump manager*. This is because the heart of this |
michael@0 | 13 | subsystem is really managing process dump files and these files are |
michael@0 | 14 | created not only from process crashes but also from hangs and other |
michael@0 | 15 | exceptional events. |
michael@0 | 16 | |
michael@0 | 17 | The crash reporter subsystem is composed of a number of pieces working |
michael@0 | 18 | together. |
michael@0 | 19 | |
michael@0 | 20 | Breakpad |
michael@0 | 21 | Breakpad is a library and set of tools to make collecting process |
michael@0 | 22 | information (notably dumps from crashes) easy. Breakpad is a 3rd |
michael@0 | 23 | party project (originaly developed by Google) that is imported into |
michael@0 | 24 | the tree. |
michael@0 | 25 | |
michael@0 | 26 | Dump files |
michael@0 | 27 | Breakpad produces files called *dump files* that hold process data |
michael@0 | 28 | (stacks, heap data, etc). |
michael@0 | 29 | |
michael@0 | 30 | Crash Reporter Client |
michael@0 | 31 | The crash reporter client is a standalone executable that is launched |
michael@0 | 32 | to handle dump files. This application optionally submits crashes to |
michael@0 | 33 | Mozilla (or the configured server). |
michael@0 | 34 | |
michael@0 | 35 | How Main-Process Crash Handling Works |
michael@0 | 36 | ===================================== |
michael@0 | 37 | |
michael@0 | 38 | The crash handler is hooked up very early in the Gecko process lifetime. |
michael@0 | 39 | It all starts in ``XREMain::XRE_mainInit()`` from ``nsAppRunner.cpp``. |
michael@0 | 40 | Assuming crash reporting is enabled, this startup function registers an |
michael@0 | 41 | exception handler for the process and tells the crash reporter subsystem |
michael@0 | 42 | about basic metadata such as the application name and version. |
michael@0 | 43 | |
michael@0 | 44 | The registration of the crash reporter exception handler doubles as |
michael@0 | 45 | initialization of the crash reporter itself. This happens in |
michael@0 | 46 | ``CrashReporter::SetExceptionHandler()`` from ``nsExceptionHandler.cpp``. |
michael@0 | 47 | The crash reporter figures out what application to use for reporting |
michael@0 | 48 | dumped crashes and where to store these dump files on disk. The Breakpad |
michael@0 | 49 | exception handler (really just a mechanism for dumping process state) is |
michael@0 | 50 | initialized as part of this function. The Breakpad exception handler is |
michael@0 | 51 | a ``google_breakpad::ExceptionHandler`` instance and it's stored as |
michael@0 | 52 | ``gExceptionHandler``. |
michael@0 | 53 | |
michael@0 | 54 | As the application runs, various other systems may write *annotations* |
michael@0 | 55 | or *notes* to the crash reporter to indicate state of the application, |
michael@0 | 56 | help with possible reasons for a current or future crash, etc. These are |
michael@0 | 57 | performed via ``CrashReporter::AnnotateCrashReport()`` and |
michael@0 | 58 | ``CrashReporter::AppendAppNotesToCrashReport()`` from |
michael@0 | 59 | ``nsExceptionHandler.h``. |
michael@0 | 60 | |
michael@0 | 61 | For well running applications, this is all that happens. However, if a |
michael@0 | 62 | crash or similar exceptional event occurs (such as a hang), we need to |
michael@0 | 63 | write a crash report. |
michael@0 | 64 | |
michael@0 | 65 | When an event worthy of writing a dump occurs, the Breakpad exception |
michael@0 | 66 | handler is invoked and Breakpad does its thing. When Breakpad has |
michael@0 | 67 | finished, it calls back into ``CrashReporter::MinidumpCallback()`` from |
michael@0 | 68 | ``nsExceptionHandler.cpp`` to tell the crash reporter about what was |
michael@0 | 69 | written. |
michael@0 | 70 | |
michael@0 | 71 | ``MinidumpCallback()`` performs a number of actions once a dump has been |
michael@0 | 72 | written. It writes a file with the time of the crash so other systems can |
michael@0 | 73 | easily determine the time of the last crash. It supplements the dump |
michael@0 | 74 | file with an *extra* file containing Mozilla-specific metadata. This data |
michael@0 | 75 | includes the annotations set via ``CrashReporter::AnnotateCrashReport()`` |
michael@0 | 76 | as well as time since last crash, whether garbage collection was active at |
michael@0 | 77 | the time of the crash, memory statistics, etc. |
michael@0 | 78 | |
michael@0 | 79 | If the *crash reporter client* is enabled, ``MinidumpCallback()`` invokes |
michael@0 | 80 | it. It simply tries to create a new *crash reporter client* process (e.g. |
michael@0 | 81 | *crashreporter.exe*) with the path to the written minidump file as an |
michael@0 | 82 | argument. |
michael@0 | 83 | |
michael@0 | 84 | The *crash reporter client* performs a number of roles. There's a lot going |
michael@0 | 85 | on, so you may want to look at ``main()`` in ``crashreporter.cpp``. First, |
michael@0 | 86 | it verifies the dump data is sane. If it isn't (e.g. required metadata is |
michael@0 | 87 | missing), the dump data is ignored. If dump data looks sane, the dump data |
michael@0 | 88 | is moved into the *pending* directory for the configured data directory |
michael@0 | 89 | (defined via the ``MOZ_CRASHREPORTER_DATA_DIRECTORY`` environment variable |
michael@0 | 90 | or from the UI). Once this is done, the main crash reporter UI is displayed |
michael@0 | 91 | via ``UIShowCrashUI()``. The crash reporter UI is platform specific: there |
michael@0 | 92 | are separate versions for Windows, OS X, and various \*NIX presentation |
michael@0 | 93 | flavors (such as GTK). The basic gist is a dialog is displayed to the user |
michael@0 | 94 | and the user has the opportunity to submit this dump data to a remote |
michael@0 | 95 | server. |
michael@0 | 96 | |
michael@0 | 97 | If a dump is submitted via the crash reporter, the raw dump files are |
michael@0 | 98 | removed from the *pending* directory and a file containing the |
michael@0 | 99 | crash ID from the remote server for the submitted dump is created in the |
michael@0 | 100 | *submitted* directory. |
michael@0 | 101 | |
michael@0 | 102 | If the user chooses not to submit a dump in the crash reporter UI, the dump |
michael@0 | 103 | files are deleted. |
michael@0 | 104 | |
michael@0 | 105 | And that's pretty much what happens when a crash/dump is written! |
michael@0 | 106 | |
michael@0 | 107 | Plugin and Child Process Crashes |
michael@0 | 108 | ================================ |
michael@0 | 109 | |
michael@0 | 110 | Crashes in plugin and child processes are also managed by the crash |
michael@0 | 111 | reporting subsystem. |
michael@0 | 112 | |
michael@0 | 113 | Child process crashes are handled by the ``mozilla::dom::CrashReporterParent`` |
michael@0 | 114 | class defined in ``dom/ipc``. When a child process crashes, the toplevel IPDL |
michael@0 | 115 | actor should check for it by calling TakeMinidump in its ``ActorDestroy`` |
michael@0 | 116 | Method: see ``mozilla::plugins::PluginModuleParent::ActorDestroy`` and |
michael@0 | 117 | ``mozilla::plugins::PluginModuleParent::ProcessFirstMinidump``. That method |
michael@0 | 118 | is responsible for calling |
michael@0 | 119 | ``mozilla::dom::CrashReporterParent::GenerateCrashReportForMinidump`` with |
michael@0 | 120 | appropriate crash annotations specific to the crash. All child-process |
michael@0 | 121 | crashes are annotated with a ``ProcessType`` annotation, such as "content" or |
michael@0 | 122 | "plugin". |
michael@0 | 123 | |
michael@0 | 124 | Submission of child process crashes is handled by application code. This |
michael@0 | 125 | code prompts the user to submit crashes in context-appropriate UI and then |
michael@0 | 126 | submits the crashes using ``CrashSubmit.jsm``. |
michael@0 | 127 | |
michael@0 | 128 | Flash Process Crashes |
michael@0 | 129 | ===================== |
michael@0 | 130 | |
michael@0 | 131 | On Windows Vista+, the Adobe Flash plugin creates two extra processes in its |
michael@0 | 132 | Firefox plugin to implement OS-level sandboxing. In order to catch crashes in |
michael@0 | 133 | these processes, Firefox injects a crash report handler into the process using the code at ``InjectCrashReporter.cpp``. When these crashes occur, the |
michael@0 | 134 | ProcessType=plugin annotation is present, and an additional annotation |
michael@0 | 135 | FlashProcessDump has the value "Sandbox" or "Broker". |
michael@0 | 136 | |
michael@0 | 137 | Plugin Hangs |
michael@0 | 138 | ============ |
michael@0 | 139 | |
michael@0 | 140 | Plugin hangs are handled as crash reports. If a plugin doesn't respond to an |
michael@0 | 141 | IPC message after 60 seconds, the plugin IPC code will take minidumps of all |
michael@0 | 142 | of the processes involved and then kill the plugin. |
michael@0 | 143 | |
michael@0 | 144 | In this case, there will be only one .ini file with the crash report metadata, |
michael@0 | 145 | but there will be multiple dump files: at least one for the browser process and |
michael@0 | 146 | one for the plugin process, and perhaps also additional dumps for the Flash |
michael@0 | 147 | sandbox and broker processes. All of these files are submitted together as a |
michael@0 | 148 | unit. Before submission, the filenames of the files are linked: |
michael@0 | 149 | |
michael@0 | 150 | - **uuid.ini** - *annotations, includes an additional_minidumps field* |
michael@0 | 151 | - **uuid.dmp** - *plugin process dump file* |
michael@0 | 152 | - **uuid-<other>.dmp** - *other process dump file as listed in additional_minidumps* |
michael@0 | 153 | |
michael@0 | 154 | Browser Hangs |
michael@0 | 155 | ============= |
michael@0 | 156 | |
michael@0 | 157 | There is a feature of Firefox that will crash Firefox if it stops processing |
michael@0 | 158 | messages after a certain period of time. This feature doesn't work well and is |
michael@0 | 159 | disabled by default. See ``xpcom/threads/HangMonitor.cpp``. Hang crashes |
michael@0 | 160 | are annotated with ``Hang=1``. |
michael@0 | 161 | |
michael@0 | 162 | about:crashes |
michael@0 | 163 | ============= |
michael@0 | 164 | |
michael@0 | 165 | If the crash reporter subsystem is enabled, the *about:crashes* |
michael@0 | 166 | page will be registered with the application. This page provides |
michael@0 | 167 | information about previous and submitted crashes. |
michael@0 | 168 | |
michael@0 | 169 | It is also possible to submit crashes from *about:crashes*. |