blob: b49093aaebb41cb34cd8cef75fdb83e0720c0912 [file] [log] [blame]
bryner1217c1f2006-09-27 01:00:32 +00001// Copyright (c) 2006, 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// ExceptionHandler can write a minidump file when an exception occurs,
31// or when WriteMinidump() is called explicitly by your program.
32//
33// To have the exception handler write minidumps when an uncaught exception
34// (crash) occurs, you should create an instance early in the execution
35// of your program, and keep it around for the entire time you want to
36// have crash handling active (typically, until shutdown).
37//
38// If you want to write minidumps without installing the exception handler,
39// you can create an ExceptionHandler with install_handler set to false,
40// then call WriteMinidump. You can also use this technique if you want to
41// use different minidump callbacks for different call sites.
42//
43// In either case, a callback function is called when a minidump is written,
44// which receives the unqiue id of the minidump. The caller can use this
45// id to collect and write additional application state, and to launch an
46// external crash-reporting application.
47//
48// It is important that creation and destruction of ExceptionHandler objects
49// be nested cleanly, when using install_handler = true.
50// Avoid the following pattern:
51// ExceptionHandler *e = new ExceptionHandler(...);
52// ExceptionHandler *f = new ExceptionHandler(...);
53// delete e;
54// This will put the exception filter stack into an inconsistent state.
brynerf1400252006-09-28 19:35:08 +000055//
56// To use this library in your project, you will need to link against
mmentovai29401d22006-10-26 18:06:43 +000057// ole32.lib.
bryner1217c1f2006-09-27 01:00:32 +000058
59#ifndef CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__
60#define CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__
61
mmentovai29401d22006-10-26 18:06:43 +000062#include <Windows.h>
63#include <DbgHelp.h>
bryner1217c1f2006-09-27 01:00:32 +000064
mmentovai12a52452006-10-27 19:47:21 +000065#pragma warning( push )
66// Disable exception handler warnings.
67#pragma warning( disable : 4530 )
68
bryner1217c1f2006-09-27 01:00:32 +000069#include <string>
70
71namespace google_airbag {
72
73using std::wstring;
74
75class ExceptionHandler {
76 public:
77 // A callback function to run after the minidump has been written.
78 // minidump_id is a unique id for the dump, so the minidump
79 // file is <dump_path>\<minidump_id>.dmp. succeeded indicates whether
80 // a minidump file was successfully written.
81 typedef void (*MinidumpCallback)(const wstring &minidump_id,
82 void *context, bool succeeded);
83
84 // Creates a new ExceptionHandler instance to handle writing minidumps.
85 // Minidump files will be written to dump_path, and the optional callback
86 // is called after writing the dump file, as described above.
87 // If install_handler is true, then a minidump will be written whenever
88 // an unhandled exception occurs. If it is false, minidumps will only
89 // be written when WriteMinidump is called.
90 ExceptionHandler(const wstring &dump_path, MinidumpCallback callback,
91 void *callback_context, bool install_handler);
92 ~ExceptionHandler();
93
mmentovai1bff57e2006-10-27 16:10:55 +000094 // Get and set the minidump path.
95 wstring dump_path() const { return dump_path_; }
96 void set_dump_path(const wstring &dump_path) { dump_path_ = dump_path; }
97
bryner1217c1f2006-09-27 01:00:32 +000098 // Writes a minidump immediately. This can be used to capture the
99 // execution state independently of a crash. Returns true on success.
100 bool WriteMinidump();
101
102 // Convenience form of WriteMinidump which does not require an
103 // ExceptionHandler instance.
104 static bool WriteMinidump(const wstring &dump_path,
105 MinidumpCallback callback, void *callback_context);
106
107 private:
108 // Function pointer type for MiniDumpWriteDump, which is looked up
109 // dynamically.
110 typedef BOOL (WINAPI *MiniDumpWriteDump_type)(
111 HANDLE hProcess,
112 DWORD dwPid,
113 HANDLE hFile,
114 MINIDUMP_TYPE DumpType,
115 CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
116 CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
117 CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
118
mmentovaib2610192006-10-31 16:49:38 +0000119 // Runs the main loop for the exception handler thread.
120 static DWORD WINAPI ExceptionHandlerThreadMain(void *lpParameter);
bryner1217c1f2006-09-27 01:00:32 +0000121
mmentovaib2610192006-10-31 16:49:38 +0000122 // Called on the exception thread when an unhandled exception occurs.
123 // Signals the exception handler thread to handle the exception.
bryner1217c1f2006-09-27 01:00:32 +0000124 static LONG WINAPI HandleException(EXCEPTION_POINTERS *exinfo);
125
mmentovaib2610192006-10-31 16:49:38 +0000126 // This is called on the exception thread or on another thread that
127 // the user wishes to produce a dump from. It calls
128 // WriteMinidumpWithException on the handler thread, avoiding stack
129 // overflows and inconsistent dumps due to writing the dump from
130 // the exception thread. If the dump is requested as a result of an
131 // exception, exinfo contains exception information, otherwise, it
132 // is NULL.
133 bool WriteMinidumpOnHandlerThread(EXCEPTION_POINTERS *exinfo);
134
135 // This function does the actual writing of a minidump. It is called
136 // on the handler thread. requesting_thread_id is the ID of the thread
137 // that requested the dump. If the dump is requested as a result of
138 // an exception, exinfo contains exception information, otherwise,
139 // it is NULL.
140 bool WriteMinidumpWithException(DWORD requesting_thread_id,
141 EXCEPTION_POINTERS *exinfo);
142
bryner1217c1f2006-09-27 01:00:32 +0000143 // Generates a new ID and stores it in next_minidump_id_.
144 void UpdateNextID();
145
146 MinidumpCallback callback_;
147 void *callback_context_;
148
149 wstring dump_path_;
mmentovai29401d22006-10-26 18:06:43 +0000150 wstring next_minidump_id_;
bryner1217c1f2006-09-27 01:00:32 +0000151
152 HMODULE dbghelp_module_;
153 MiniDumpWriteDump_type minidump_write_dump_;
154
155 ExceptionHandler *previous_handler_; // current_handler_ before us
156 LPTOP_LEVEL_EXCEPTION_FILTER previous_filter_;
157
158 // the currently-installed ExceptionHandler, of which there can be only 1
159 static ExceptionHandler *current_handler_;
160
mmentovaib2610192006-10-31 16:49:38 +0000161 // The exception handler thread, if one has been created.
162 static HANDLE handler_thread_;
163
164 // The critical section enforcing the requirement that only one exception be
165 // handled at a time.
166 static CRITICAL_SECTION handler_critical_section_;
167
168 // Semaphores used to move exception handling between the exception thread
169 // and the handler thread. handler_start_semaphore_ is signalled by the
170 // exception thread to wake up the handler thread when an exception occurs.
171 // handler_finish_semaphore_ is signalled by the handler thread to wake up
172 // the exception thread when handling is complete.
173 static HANDLE handler_start_semaphore_;
174 static HANDLE handler_finish_semaphore_;
175
176 // The next 3 fields are static data passed from the requesting thread to
177 // the handler thread.
178
179 // The ExceptionHandler through which a request to write a dump was routed.
180 // This will be the same as current_handler_ for exceptions, but
181 // user-requested dumps may be routed through any live ExceptionHandler.
182 static ExceptionHandler *requesting_handler_;
183
184 // The thread ID of the thread requesting the dump (either the exception
185 // thread or any other thread that called WriteMinidump directly).
186 static DWORD requesting_thread_id_;
187
188 // The exception info passed to the exception handler on the exception
189 // thread, if an exception occurred. NULL for user-requested dumps.
190 static EXCEPTION_POINTERS *exception_info_;
191
192 // The return value of the handler, passed from the handler thread back to
193 // the requesting thread.
194 static bool handler_return_value_;
195
bryner1217c1f2006-09-27 01:00:32 +0000196 // disallow copy ctor and operator=
197 explicit ExceptionHandler(const ExceptionHandler &);
198 void operator=(const ExceptionHandler &);
199};
200
201} // namespace google_airbag
202
mmentovai12a52452006-10-27 19:47:21 +0000203#pragma warning( pop )
204
bryner1217c1f2006-09-27 01:00:32 +0000205#endif // CLIENT_WINDOWS_HANDLER_EXCEPTION_HANDLER_H__