1 // Copyright 2007 Google LLC 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google LLC nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 // 29 // Author: Alfred Peng 30 31 #ifndef CLIENT_SOLARIS_HANDLER_EXCEPTION_HANDLER_H__ 32 #define CLIENT_SOLARIS_HANDLER_EXCEPTION_HANDLER_H__ 33 34 #include <map> 35 #include <string> 36 #include <vector> 37 38 #include "client/solaris/handler/minidump_generator.h" 39 40 namespace google_breakpad { 41 42 using std::string; 43 44 // 45 // ExceptionHandler 46 // 47 // ExceptionHandler can write a minidump file when an exception occurs, 48 // or when WriteMinidump() is called explicitly by your program. 49 // 50 // To have the exception handler write minidumps when an uncaught exception 51 // (crash) occurs, you should create an instance early in the execution 52 // of your program, and keep it around for the entire time you want to 53 // have crash handling active (typically, until shutdown). 54 // (NOTE): There should be only one this kind of exception handler 55 // object per process. 56 // 57 // If you want to write minidumps without installing the exception handler, 58 // you can create an ExceptionHandler with install_handler set to false, 59 // then call WriteMinidump. You can also use this technique if you want to 60 // use different minidump callbacks for different call sites. 61 // 62 // In either case, a callback function is called when a minidump is written, 63 // which receives the unqiue id of the minidump. The caller can use this 64 // id to collect and write additional application state, and to launch an 65 // external crash-reporting application. 66 // 67 // Caller should try to make the callbacks as crash-friendly as possible, 68 // it should avoid use heap memory allocation as much as possible. 69 // 70 class ExceptionHandler { 71 public: 72 // A callback function to run before Breakpad performs any substantial 73 // processing of an exception. A FilterCallback is called before writing 74 // a minidump. context is the parameter supplied by the user as 75 // callback_context when the handler was created. 76 // 77 // If a FilterCallback returns true, Breakpad will continue processing, 78 // attempting to write a minidump. If a FilterCallback returns false, 79 // Breakpad will immediately report the exception as unhandled without 80 // writing a minidump, allowing another handler the opportunity to handle it. 81 typedef bool (*FilterCallback)(void* context); 82 83 // A callback function to run after the minidump has been written. 84 // minidump_id is a unique id for the dump, so the minidump 85 // file is <dump_path>/<minidump_id>.dmp. context is the parameter supplied 86 // by the user as callback_context when the handler was created. succeeded 87 // indicates whether a minidump file was successfully written. 88 // 89 // If an exception occurred and the callback returns true, Breakpad will 90 // treat the exception as fully-handled, suppressing any other handlers from 91 // being notified of the exception. If the callback returns false, Breakpad 92 // will treat the exception as unhandled, and allow another handler to handle 93 // it. If there are no other handlers, Breakpad will report the exception to 94 // the system as unhandled, allowing a debugger or native crash dialog the 95 // opportunity to handle the exception. Most callback implementations 96 // should normally return the value of |succeeded|, or when they wish to 97 // not report an exception of handled, false. Callbacks will rarely want to 98 // return true directly (unless |succeeded| is true). 99 typedef bool (*MinidumpCallback)(const char* dump_path, 100 const char* minidump_id, 101 void* context, 102 bool succeeded); 103 104 // Creates a new ExceptionHandler instance to handle writing minidumps. 105 // Before writing a minidump, the optional filter callback will be called. 106 // Its return value determines whether or not Breakpad should write a 107 // minidump. Minidump files will be written to dump_path, and the optional 108 // callback is called after writing the dump file, as described above. 109 // If install_handler is true, then a minidump will be written whenever 110 // an unhandled exception occurs. If it is false, minidumps will only 111 // be written when WriteMinidump is called. 112 ExceptionHandler(const string& dump_path, 113 FilterCallback filter, MinidumpCallback callback, 114 void* callback_context, 115 bool install_handler); 116 ~ExceptionHandler(); 117 118 // Get and Set the minidump path. dump_path()119 string dump_path() const { return dump_path_; } set_dump_path(const string & dump_path)120 void set_dump_path(const string& dump_path) { 121 dump_path_ = dump_path; 122 dump_path_c_ = dump_path_.c_str(); 123 } 124 125 // Writes a minidump immediately. This can be used to capture the 126 // execution state independently of a crash. Returns true on success. 127 bool WriteMinidump(); 128 129 // Convenience form of WriteMinidump which does not require an 130 // ExceptionHandler instance. 131 static bool WriteMinidump(const string& dump_path, 132 MinidumpCallback callback, 133 void* callback_context); 134 135 private: 136 // Setup crash handler. 137 void SetupHandler(); 138 // Setup signal handler for a signal. 139 void SetupHandler(int signo); 140 // Teardown the handler for a signal. 141 void TeardownHandler(int signo); 142 // Teardown all handlers. 143 void TeardownAllHandlers(); 144 145 // Runs the main loop for the exception handler thread. 146 static void* ExceptionHandlerThreadMain(void* lpParameter); 147 148 // Signal handler. 149 static void HandleException(int signo); 150 151 // Write all the information to the dump file. 152 // If called from a signal handler, sighandler_ebp is the ebp of 153 // that signal handler's frame, and sig_ctx is an out parameter 154 // that will be set to point at the ucontext_t that was placed 155 // on the stack by the kernel. You can pass zero and NULL 156 // for the second and third parameters if you are not calling 157 // this from a signal handler. 158 bool InternalWriteMinidump(int signo, uintptr_t sighandler_ebp, 159 ucontext_t** sig_ctx); 160 161 private: 162 // The callbacks before and after writing the dump file. 163 FilterCallback filter_; 164 MinidumpCallback callback_; 165 void* callback_context_; 166 167 // The directory in which a minidump will be written, set by the dump_path 168 // argument to the constructor, or set_dump_path. 169 string dump_path_; 170 // C style dump path. Keep this when setting dump path, since calling 171 // c_str() of std::string when crashing may not be safe. 172 const char* dump_path_c_; 173 174 // True if the ExceptionHandler installed an unhandled exception filter 175 // when created (with an install_handler parameter set to true). 176 bool installed_handler_; 177 178 // Keep the previous handlers for the signal. 179 typedef void (*sighandler_t)(int); 180 std::map<int, sighandler_t> old_handlers_; 181 182 // The global exception handler stack. This is need becuase there may exist 183 // multiple ExceptionHandler instances in a process. Each will have itself 184 // registered in this stack. 185 static std::vector<ExceptionHandler*>* handler_stack_; 186 // The index of the handler that should handle the next exception. 187 static int handler_stack_index_; 188 static pthread_mutex_t handler_stack_mutex_; 189 190 // The minidump generator. 191 MinidumpGenerator minidump_generator_; 192 193 // disallow copy ctor and operator= 194 explicit ExceptionHandler(const ExceptionHandler&); 195 void operator=(const ExceptionHandler&); 196 }; 197 198 } // namespace google_breakpad 199 200 #endif // CLIENT_SOLARIS_HANDLER_EXCEPTION_HANDLER_H__ 201