exception_handler.h revision 662b6da59dd0218ea5496c085cb010d59f2b4219
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 <vector>
34#include <string>
35
36#include <signal.h>
37#include <stdio.h>
38
39#include "client/linux/crash_generation/crash_generation_client.h"
40#include "processor/scoped_ptr.h"
41
42struct sigaction;
43
44namespace google_breakpad {
45
46class ExceptionHandler;
47
48// ExceptionHandler
49//
50// ExceptionHandler can write a minidump file when an exception occurs,
51// or when WriteMinidump() is called explicitly by your program.
52//
53// To have the exception handler write minidumps when an uncaught exception
54// (crash) occurs, you should create an instance early in the execution
55// of your program, and keep it around for the entire time you want to
56// have crash handling active (typically, until shutdown).
57// (NOTE): There should be only be one this kind of exception handler
58// object per process.
59//
60// If you want to write minidumps without installing the exception handler,
61// you can create an ExceptionHandler with install_handler set to false,
62// then call WriteMinidump.  You can also use this technique if you want to
63// use different minidump callbacks for different call sites.
64//
65// In either case, a callback function is called when a minidump is written,
66// which receives the unqiue id of the minidump.  The caller can use this
67// id to collect and write additional application state, and to launch an
68// external crash-reporting application.
69//
70// Caller should try to make the callbacks as crash-friendly as possible,
71// it should avoid use heap memory allocation as much as possible.
72class ExceptionHandler {
73 public:
74  // A callback function to run before Breakpad performs any substantial
75  // processing of an exception.  A FilterCallback is called before writing
76  // a minidump.  context is the parameter supplied by the user as
77  // callback_context when the handler was created.
78  //
79  // If a FilterCallback returns true, Breakpad will continue processing,
80  // attempting to write a minidump.  If a FilterCallback returns false,
81  // Breakpad  will immediately report the exception as unhandled without
82  // writing a minidump, allowing another handler the opportunity to handle it.
83  typedef bool (*FilterCallback)(void *context);
84
85  // A callback function to run after the minidump has been written.
86  // minidump_id is a unique id for the dump, so the minidump
87  // file is <dump_path>\<minidump_id>.dmp.  context is the parameter supplied
88  // by the user as callback_context when the handler was created.  succeeded
89  // indicates whether a minidump file was successfully written.
90  //
91  // If an exception occurred and the callback returns true, Breakpad will
92  // treat the exception as fully-handled, suppressing any other handlers from
93  // being notified of the exception.  If the callback returns false, Breakpad
94  // will treat the exception as unhandled, and allow another handler to handle
95  // it. If there are no other handlers, Breakpad will report the exception to
96  // the system as unhandled, allowing a debugger or native crash dialog the
97  // opportunity to handle the exception.  Most callback implementations
98  // should normally return the value of |succeeded|, or when they wish to
99  // not report an exception of handled, false.  Callbacks will rarely want to
100  // return true directly (unless |succeeded| is true).
101  typedef bool (*MinidumpCallback)(const char *dump_path,
102                                   const char *minidump_id,
103                                   void *context,
104                                   bool succeeded);
105
106  // In certain cases, a user may wish to handle the generation of the minidump
107  // themselves. In this case, they can install a handler callback which is
108  // called when a crash has occured. If this function returns true, no other
109  // processing of occurs and the process will shortly be crashed. If this
110  // returns false, the normal processing continues.
111  typedef bool (*HandlerCallback)(const void* crash_context,
112                                  size_t crash_context_size,
113                                  void* context);
114
115  // Creates a new ExceptionHandler instance to handle writing minidumps.
116  // Before writing a minidump, the optional filter callback will be called.
117  // Its return value determines whether or not Breakpad should write a
118  // minidump.  Minidump files will be written to dump_path, and the optional
119  // callback is called after writing the dump file, as described above.
120  // If install_handler is true, then a minidump will be written whenever
121  // an unhandled exception occurs.  If it is false, minidumps will only
122  // be written when WriteMinidump is called.
123  ExceptionHandler(const std::string &dump_path,
124                   FilterCallback filter, MinidumpCallback callback,
125                   void *callback_context,
126                   bool install_handler);
127
128  // Creates a new ExceptionHandler instance that can attempt to
129  // perform out-of-process dump generation if server_fd is valid. If
130  // server_fd is invalid, in-process dump generation will be
131  // used. See the above ctor for a description of the other
132  // parameters.
133  ExceptionHandler(const std::string& dump_path,
134                   FilterCallback filter, MinidumpCallback callback,
135                   void* callback_context,
136                   bool install_handler,
137                   const int server_fd);
138
139  ~ExceptionHandler();
140
141  // Get and set the minidump path.
142  std::string dump_path() const { return dump_path_; }
143  void set_dump_path(const std::string &dump_path) {
144    dump_path_ = dump_path;
145    dump_path_c_ = dump_path_.c_str();
146    UpdateNextID();
147  }
148
149  void set_crash_handler(HandlerCallback callback) {
150    crash_handler_ = callback;
151  }
152
153  // Writes a minidump immediately.  This can be used to capture the
154  // execution state independently of a crash.  Returns true on success.
155  bool WriteMinidump();
156
157  // Convenience form of WriteMinidump which does not require an
158  // ExceptionHandler instance.
159  static bool WriteMinidump(const std::string &dump_path,
160                            MinidumpCallback callback,
161                            void *callback_context);
162
163  // This structure is passed to minidump_writer.h:WriteMinidump via an opaque
164  // blob. It shouldn't be needed in any user code.
165  struct CrashContext {
166    siginfo_t siginfo;
167    pid_t tid;  // the crashing thread.
168    struct ucontext context;
169#if !defined(__ARM_EABI__)
170    // #ifdef this out because FP state is not part of user ABI for Linux ARM.
171    struct _libc_fpstate float_state;
172#endif
173  };
174
175  // Returns whether out-of-process dump generation is used or not.
176  bool IsOutOfProcess() const {
177      return crash_generation_client_.get() != NULL;
178  }
179
180 private:
181  void Init(const std::string &dump_path,
182            const int server_fd);
183  bool InstallHandlers();
184  void UninstallHandlers();
185  void PreresolveSymbols();
186  bool GenerateDump(CrashContext *context);
187  void SendContinueSignalToChild();
188  void WaitForContinueSignal();
189
190  void UpdateNextID();
191  static void SignalHandler(int sig, siginfo_t* info, void* uc);
192  bool HandleSignal(int sig, siginfo_t* info, void* uc);
193  static int ThreadEntry(void* arg);
194  bool DoDump(pid_t crashing_process, const void* context,
195              size_t context_size);
196
197  const FilterCallback filter_;
198  const MinidumpCallback callback_;
199  void* const callback_context_;
200
201  scoped_ptr<CrashGenerationClient> crash_generation_client_;
202
203  std::string dump_path_;
204  std::string next_minidump_path_;
205  std::string next_minidump_id_;
206
207  // Pointers to C-string representations of the above. These are set
208  // when the above are set so we can avoid calling c_str during
209  // an exception.
210  const char* dump_path_c_;
211  const char* next_minidump_path_c_;
212  const char* next_minidump_id_c_;
213
214  const bool handler_installed_;
215  void* signal_stack;  // the handler stack.
216  HandlerCallback crash_handler_;
217
218  // The global exception handler stack. This is need becuase there may exist
219  // multiple ExceptionHandler instances in a process. Each will have itself
220  // registered in this stack.
221  static std::vector<ExceptionHandler*> *handler_stack_;
222  // The index of the handler that should handle the next exception.
223  static unsigned handler_stack_index_;
224  static pthread_mutex_t handler_stack_mutex_;
225
226  // A vector of the old signal handlers.
227  std::vector<std::pair<int, struct sigaction *> > old_handlers_;
228
229  // We need to explicitly enable ptrace of parent processes on some
230  // kernels, but we need to know the PID of the cloned process before we
231  // can do this. We create a pipe which we can use to block the
232  // cloned process after creating it, until we have explicitly enabled
233  // ptrace. This is used to store the file descriptors for the pipe
234  int fdes[2];
235};
236
237}  // namespace google_breakpad
238
239#endif  // CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_
240