1 // Copyright (c) 2007, 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 // Author: Alfred Peng 31 32 #ifndef CLIENT_SOLARIS_HANDLER_EXCEPTION_HANDLER_H__ 33 #define CLIENT_SOLARIS_HANDLER_EXCEPTION_HANDLER_H__ 34 35 #include <map> 36 #include <string> 37 #include <vector> 38 39 #include "client/solaris/handler/minidump_generator.h" 40 41 namespace google_breakpad { 42 43 using std::string; 44 45 // 46 // ExceptionHandler 47 // 48 // ExceptionHandler can write a minidump file when an exception occurs, 49 // or when WriteMinidump() is called explicitly by your program. 50 // 51 // To have the exception handler write minidumps when an uncaught exception 52 // (crash) occurs, you should create an instance early in the execution 53 // of your program, and keep it around for the entire time you want to 54 // have crash handling active (typically, until shutdown). 55 // (NOTE): There should be only one this kind of exception handler 56 // object per process. 57 // 58 // If you want to write minidumps without installing the exception handler, 59 // you can create an ExceptionHandler with install_handler set to false, 60 // then call WriteMinidump. You can also use this technique if you want to 61 // use different minidump callbacks for different call sites. 62 // 63 // In either case, a callback function is called when a minidump is written, 64 // which receives the unqiue id of the minidump. The caller can use this 65 // id to collect and write additional application state, and to launch an 66 // external crash-reporting application. 67 // 68 // Caller should try to make the callbacks as crash-friendly as possible, 69 // it should avoid use heap memory allocation as much as possible. 70 // 71 class ExceptionHandler { 72 public: 73 // A callback function to run before Breakpad performs any substantial 74 // processing of an exception. A FilterCallback is called before writing 75 // a minidump. context is the parameter supplied by the user as 76 // callback_context when the handler was created. 77 // 78 // If a FilterCallback returns true, Breakpad will continue processing, 79 // attempting to write a minidump. If a FilterCallback returns false, 80 // Breakpad will immediately report the exception as unhandled without 81 // writing a minidump, allowing another handler the opportunity to handle it. 82 typedef bool (*FilterCallback)(void *context); 83 84 // A callback function to run after the minidump has been written. 85 // minidump_id is a unique id for the dump, so the minidump 86 // file is <dump_path>/<minidump_id>.dmp. context is the parameter supplied 87 // by the user as callback_context when the handler was created. succeeded 88 // indicates whether a minidump file was successfully written. 89 // 90 // If an exception occurred and the callback returns true, Breakpad will 91 // treat the exception as fully-handled, suppressing any other handlers from 92 // being notified of the exception. If the callback returns false, Breakpad 93 // will treat the exception as unhandled, and allow another handler to handle 94 // it. If there are no other handlers, Breakpad will report the exception to 95 // the system as unhandled, allowing a debugger or native crash dialog the 96 // opportunity to handle the exception. Most callback implementations 97 // should normally return the value of |succeeded|, or when they wish to 98 // not report an exception of handled, false. Callbacks will rarely want to 99 // return true directly (unless |succeeded| is true). 100 typedef bool (*MinidumpCallback)(const char *dump_path, 101 const char *minidump_id, 102 void *context, 103 bool succeeded); 104 105 // Creates a new ExceptionHandler instance to handle writing minidumps. 106 // Before writing a minidump, the optional filter callback will be called. 107 // Its return value determines whether or not Breakpad should write a 108 // minidump. Minidump files will be written to dump_path, and the optional 109 // callback is called after writing the dump file, as described above. 110 // If install_handler is true, then a minidump will be written whenever 111 // an unhandled exception occurs. If it is false, minidumps will only 112 // be written when WriteMinidump is called. 113 ExceptionHandler(const string &dump_path, 114 FilterCallback filter, MinidumpCallback callback, 115 void *callback_context, 116 bool install_handler); 117 ~ExceptionHandler(); 118 119 // Get and Set the minidump path. 120 string dump_path() const { return dump_path_; } 121 void set_dump_path(const string &dump_path) { 122 dump_path_ = dump_path; 123 dump_path_c_ = dump_path_.c_str(); 124 } 125 126 // Writes a minidump immediately. This can be used to capture the 127 // execution state independently of a crash. Returns true on success. 128 bool WriteMinidump(); 129 130 // Convenience form of WriteMinidump which does not require an 131 // ExceptionHandler instance. 132 static bool WriteMinidump(const string &dump_path, 133 MinidumpCallback callback, 134 void *callback_context); 135 136 private: 137 // Setup crash handler. 138 void SetupHandler(); 139 // Setup signal handler for a signal. 140 void SetupHandler(int signo); 141 // Teardown the handler for a signal. 142 void TeardownHandler(int signo); 143 // Teardown all handlers. 144 void TeardownAllHandlers(); 145 146 // Runs the main loop for the exception handler thread. 147 static void* ExceptionHandlerThreadMain(void *lpParameter); 148 149 // Signal handler. 150 static void HandleException(int signo); 151 152 // Write all the information to the dump file. 153 // If called from a signal handler, sighandler_ebp is the ebp of 154 // that signal handler's frame, and sig_ctx is an out parameter 155 // that will be set to point at the ucontext_t that was placed 156 // on the stack by the kernel. You can pass zero and NULL 157 // for the second and third parameters if you are not calling 158 // this from a signal handler. 159 bool InternalWriteMinidump(int signo, uintptr_t sighandler_ebp, 160 ucontext_t **sig_ctx); 161 162 private: 163 // The callbacks before and after writing the dump file. 164 FilterCallback filter_; 165 MinidumpCallback callback_; 166 void *callback_context_; 167 168 // The directory in which a minidump will be written, set by the dump_path 169 // argument to the constructor, or set_dump_path. 170 string dump_path_; 171 // C style dump path. Keep this when setting dump path, since calling 172 // c_str() of std::string when crashing may not be safe. 173 const char *dump_path_c_; 174 175 // True if the ExceptionHandler installed an unhandled exception filter 176 // when created (with an install_handler parameter set to true). 177 bool installed_handler_; 178 179 // Keep the previous handlers for the signal. 180 typedef void (*sighandler_t)(int); 181 std::map<int, sighandler_t> old_handlers_; 182 183 // The global exception handler stack. This is need becuase there may exist 184 // multiple ExceptionHandler instances in a process. Each will have itself 185 // registered in this stack. 186 static std::vector<ExceptionHandler *> *handler_stack_; 187 // The index of the handler that should handle the next exception. 188 static int handler_stack_index_; 189 static pthread_mutex_t handler_stack_mutex_; 190 191 // The minidump generator. 192 MinidumpGenerator minidump_generator_; 193 194 // disallow copy ctor and operator= 195 explicit ExceptionHandler(const ExceptionHandler &); 196 void operator=(const ExceptionHandler &); 197 }; 198 199 } // namespace google_breakpad 200 201 #endif // CLIENT_SOLARIS_HANDLER_EXCEPTION_HANDLER_H__ 202