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