exception_handler.h revision 426eb2fb197a6e640609fd40273bd30fd2d81ebb
1// Copyright (c) 2010 Google Inc. 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: 7// 8// * Redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer. 10// * Redistributions in binary form must reproduce the above 11// copyright notice, this list of conditions and the following disclaimer 12// in the documentation and/or other materials provided with the 13// distribution. 14// * Neither the name of Google Inc. nor the names of its 15// contributors may be used to endorse or promote products derived from 16// this software without specific prior written permission. 17// 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30#ifndef CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_ 31#define CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_ 32 33#include <string> 34#include <vector> 35 36#include <pthread.h> 37#include <signal.h> 38#include <stdint.h> 39#include <stdio.h> 40 41#if defined(__ANDROID__) 42#include "client/linux/android_ucontext.h" 43#endif 44#include "client/linux/crash_generation/crash_generation_client.h" 45#include "client/linux/minidump_writer/minidump_writer.h" 46#include "google_breakpad/common/minidump_format.h" 47#include "processor/scoped_ptr.h" 48 49struct sigaction; 50 51namespace google_breakpad { 52 53class ExceptionHandler; 54 55// ExceptionHandler 56// 57// ExceptionHandler can write a minidump file when an exception occurs, 58// or when WriteMinidump() is called explicitly by your program. 59// 60// To have the exception handler write minidumps when an uncaught exception 61// (crash) occurs, you should create an instance early in the execution 62// of your program, and keep it around for the entire time you want to 63// have crash handling active (typically, until shutdown). 64// (NOTE): There should be only be one this kind of exception handler 65// object per process. 66// 67// If you want to write minidumps without installing the exception handler, 68// you can create an ExceptionHandler with install_handler set to false, 69// then call WriteMinidump. You can also use this technique if you want to 70// use different minidump callbacks for different call sites. 71// 72// In either case, a callback function is called when a minidump is written, 73// which receives the unqiue id of the minidump. The caller can use this 74// id to collect and write additional application state, and to launch an 75// external crash-reporting application. 76// 77// Caller should try to make the callbacks as crash-friendly as possible, 78// it should avoid use heap memory allocation as much as possible. 79class ExceptionHandler { 80 public: 81 // A callback function to run before Breakpad performs any substantial 82 // processing of an exception. A FilterCallback is called before writing 83 // a minidump. context is the parameter supplied by the user as 84 // callback_context when the handler was created. 85 // 86 // If a FilterCallback returns true, Breakpad will continue processing, 87 // attempting to write a minidump. If a FilterCallback returns false, 88 // Breakpad will immediately report the exception as unhandled without 89 // writing a minidump, allowing another handler the opportunity to handle it. 90 typedef bool (*FilterCallback)(void *context); 91 92 // A callback function to run after the minidump has been written. 93 // minidump_id is a unique id for the dump, so the minidump 94 // file is <dump_path>\<minidump_id>.dmp. context is the parameter supplied 95 // by the user as callback_context when the handler was created. succeeded 96 // indicates whether a minidump file was successfully written. 97 // 98 // If an exception occurred and the callback returns true, Breakpad will 99 // treat the exception as fully-handled, suppressing any other handlers from 100 // being notified of the exception. If the callback returns false, Breakpad 101 // will treat the exception as unhandled, and allow another handler to handle 102 // it. If there are no other handlers, Breakpad will report the exception to 103 // the system as unhandled, allowing a debugger or native crash dialog the 104 // opportunity to handle the exception. Most callback implementations 105 // should normally return the value of |succeeded|, or when they wish to 106 // not report an exception of handled, false. Callbacks will rarely want to 107 // return true directly (unless |succeeded| is true). 108 typedef bool (*MinidumpCallback)(const char *dump_path, 109 const char *minidump_id, 110 void *context, 111 bool succeeded); 112 113 // In certain cases, a user may wish to handle the generation of the minidump 114 // themselves. In this case, they can install a handler callback which is 115 // called when a crash has occurred. If this function returns true, no other 116 // processing of occurs and the process will shortly be crashed. If this 117 // returns false, the normal processing continues. 118 typedef bool (*HandlerCallback)(const void* crash_context, 119 size_t crash_context_size, 120 void* context); 121 122 // Creates a new ExceptionHandler instance to handle writing minidumps. 123 // Before writing a minidump, the optional filter callback will be called. 124 // Its return value determines whether or not Breakpad should write a 125 // minidump. Minidump files will be written to dump_path, and the optional 126 // callback is called after writing the dump file, as described above. 127 // If install_handler is true, then a minidump will be written whenever 128 // an unhandled exception occurs. If it is false, minidumps will only 129 // be written when WriteMinidump is called. 130 ExceptionHandler(const std::string &dump_path, 131 FilterCallback filter, MinidumpCallback callback, 132 void *callback_context, 133 bool install_handler); 134 135 // Creates a new ExceptionHandler instance that can attempt to 136 // perform out-of-process dump generation if server_fd is valid. If 137 // server_fd is invalid, in-process dump generation will be 138 // used. See the above ctor for a description of the other 139 // parameters. 140 ExceptionHandler(const std::string& dump_path, 141 FilterCallback filter, MinidumpCallback callback, 142 void* callback_context, 143 bool install_handler, 144 const int server_fd); 145 146 ~ExceptionHandler(); 147 148 // Get and set the minidump path. 149 std::string dump_path() const { return dump_path_; } 150 void set_dump_path(const std::string &dump_path) { 151 dump_path_ = dump_path; 152 dump_path_c_ = dump_path_.c_str(); 153 UpdateNextID(); 154 } 155 156 void set_crash_handler(HandlerCallback callback) { 157 crash_handler_ = callback; 158 } 159 160 // Writes a minidump immediately. This can be used to capture the 161 // execution state independently of a crash. Returns true on success. 162 bool WriteMinidump(); 163 164 // Convenience form of WriteMinidump which does not require an 165 // ExceptionHandler instance. 166 static bool WriteMinidump(const std::string &dump_path, 167 MinidumpCallback callback, 168 void *callback_context); 169 170 // This structure is passed to minidump_writer.h:WriteMinidump via an opaque 171 // blob. It shouldn't be needed in any user code. 172 struct CrashContext { 173 siginfo_t siginfo; 174 pid_t tid; // the crashing thread. 175 struct ucontext context; 176#if !defined(__ARM_EABI__) 177 // #ifdef this out because FP state is not part of user ABI for Linux ARM. 178 struct _libc_fpstate float_state; 179#endif 180 }; 181 182 // Returns whether out-of-process dump generation is used or not. 183 bool IsOutOfProcess() const { 184 return crash_generation_client_.get() != NULL; 185 } 186 187 // Add information about a memory mapping. This can be used if 188 // a custom library loader is used that maps things in a way 189 // that the linux dumper can't handle by reading the maps file. 190 void AddMappingInfo(const std::string& name, 191 const u_int8_t identifier[sizeof(MDGUID)], 192 uintptr_t start_address, 193 size_t mapping_size, 194 size_t file_offset); 195 196 private: 197 void Init(const std::string &dump_path, 198 const int server_fd); 199 bool InstallHandlers(); 200 void UninstallHandlers(); 201 void PreresolveSymbols(); 202 bool GenerateDump(CrashContext *context); 203 void SendContinueSignalToChild(); 204 void WaitForContinueSignal(); 205 206 void UpdateNextID(); 207 static void SignalHandler(int sig, siginfo_t* info, void* uc); 208 bool HandleSignal(int sig, siginfo_t* info, void* uc); 209 static int ThreadEntry(void* arg); 210 bool DoDump(pid_t crashing_process, const void* context, 211 size_t context_size); 212 213 const FilterCallback filter_; 214 const MinidumpCallback callback_; 215 void* const callback_context_; 216 217 scoped_ptr<CrashGenerationClient> crash_generation_client_; 218 219 std::string dump_path_; 220 std::string next_minidump_path_; 221 std::string next_minidump_id_; 222 223 // Pointers to C-string representations of the above. These are set 224 // when the above are set so we can avoid calling c_str during 225 // an exception. 226 const char* dump_path_c_; 227 const char* next_minidump_path_c_; 228 const char* next_minidump_id_c_; 229 230 const bool handler_installed_; 231 HandlerCallback crash_handler_; 232 233 // The global exception handler stack. This is need becuase there may exist 234 // multiple ExceptionHandler instances in a process. Each will have itself 235 // registered in this stack. 236 static std::vector<ExceptionHandler*> *handler_stack_; 237 // The index of the handler that should handle the next exception. 238 static unsigned handler_stack_index_; 239 static pthread_mutex_t handler_stack_mutex_; 240 241 // A vector of the old signal handlers. 242 std::vector<std::pair<int, struct sigaction *> > old_handlers_; 243 244 // We need to explicitly enable ptrace of parent processes on some 245 // kernels, but we need to know the PID of the cloned process before we 246 // can do this. We create a pipe which we can use to block the 247 // cloned process after creating it, until we have explicitly enabled 248 // ptrace. This is used to store the file descriptors for the pipe 249 int fdes[2]; 250 251 // Callers can add extra info about mappings for cases where the 252 // dumper code cannot extract enough information from /proc/<pid>/maps. 253 MappingList mapping_list_; 254}; 255 256} // namespace google_breakpad 257 258#endif // CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_ 259