Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: chrome_frame/exception_barrier.h

Issue 1748016: Avoid reporting crashes for exceptions that hit our SEH from calls to the ori... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4 //
5 // A class to make it easy to tag exception propagation boundaries and 5 // A class to make it easy to tag exception propagation boundaries and
6 // get crash reports of exceptions that pass over same. 6 // get crash reports of exceptions that pass over same.
7 //
8 // An exception barrier is used to report exceptions that pass through
9 // a boundary where exceptions shouldn't pass, such as e.g. COM interface
10 // boundaries.
11 // This is handy for any kind of plugin code, where if the exception passes
12 // through unhindered, it'll either be swallowed by an SEH exception handler
13 // above us on the stack, or be reported as an unhandled exception for
14 // the application hosting the plugin code.
15 //
16 // IMPORTANT NOTE: This class has crash_reporting disabled by default. To
17 // enable crash reporting call:
18 //
19 // @code
20 // ExceptionBarrierBase::set_crash_handling(true)
21 // @endcode
22 //
23 // somewhere in your initialization code.
24 //
25 // Then, to use this class, simply instantiate an ExceptionBarrier just inside
26 // the code boundary, like this:
27 // @code
28 // HRESULT SomeObject::SomeCOMMethod(...) {
29 // ExceptionBarrier report_crashes;
30 //
31 // ... other code here ...
32 // }
33 // @endcode
34 //
35 // There are three ExceptionBarrier types defined here:
36 // 1) ExceptionBarrier which reports all crashes it sees.
37 // 2) ExceptionBarrierReportOnlyModule which reports only crashes occurring
38 // in this module.
39 // 3) ExceptionBarrierCustomHandler which calls the handler set by a call
40 // to ExceptionBarrierCallCustomHandler::set_custom_handler(). Note that
41 // there is one custom handler for all ExceptionBarrierCallCustomHandler
42 // instances. If set_custom_handler() is never called, this places an
43 // SEH in the chain that just returns ExceptionContinueSearch.
44
7 #ifndef CHROME_FRAME_EXCEPTION_BARRIER_H_ 45 #ifndef CHROME_FRAME_EXCEPTION_BARRIER_H_
8 #define CHROME_FRAME_EXCEPTION_BARRIER_H_ 46 #define CHROME_FRAME_EXCEPTION_BARRIER_H_
9 47
10 #include <windows.h> 48 #include <windows.h>
11 49
12 /// This is the type dictated for an exception handler by the platform ABI 50 extern "C" IMAGE_DOS_HEADER __ImageBase;
13 /// @see _except_handler in excpt.h
14 typedef EXCEPTION_DISPOSITION (__cdecl *ExceptionHandlerFunc)(
15 struct _EXCEPTION_RECORD *exception_record,
16 void * establisher_frame,
17 struct _CONTEXT *context,
18 void * reserved);
19 51
20 /// The type of an exception record in the exception handler chain 52 // This is the type dictated for an exception handler by the platform ABI
53 // @see _except_handler in excpt.h
54 typedef EXCEPTION_DISPOSITION (__cdecl* ExceptionHandlerFunc)(
55 struct _EXCEPTION_RECORD* exception_record,
56 void* establisher_frame,
57 struct _CONTEXT* context,
58 void* reserved);
59
60 // The type of an exception record in the exception handler chain
21 struct EXCEPTION_REGISTRATION { 61 struct EXCEPTION_REGISTRATION {
22 EXCEPTION_REGISTRATION *prev; 62 EXCEPTION_REGISTRATION* prev;
23 ExceptionHandlerFunc handler; 63 ExceptionHandlerFunc handler;
24 }; 64 };
25 65
26 /// This is our raw exception handler, it must be declared extern "C" to 66 // This is our raw exception handler, it must be declared extern "C" to
27 /// match up with the SAFESEH declaration in our corresponding ASM file 67 // match up with the SAFESEH declaration in our corresponding ASM file.
28 extern "C" EXCEPTION_DISPOSITION __cdecl 68 extern "C" EXCEPTION_DISPOSITION __cdecl
29 ExceptionBarrierHandler(struct _EXCEPTION_RECORD *exception_record, 69 ExceptionBarrierHandler(struct _EXCEPTION_RECORD* exception_record,
30 void * establisher_frame, 70 void* establisher_frame,
31 struct _CONTEXT *context, 71 struct _CONTEXT* context,
32 void * reserved); 72 void* reserved);
33 73
34 /// An exception barrier is used to report exceptions that pass through 74 // An alternate raw exception handler that reports crashes only for the current
35 /// a boundary where exceptions shouldn't pass, such as e.g. COM interface 75 // module. It must be declared extern "C" to match up with the SAFESEH
36 /// boundaries. 76 // declaration in our corresponding ASM file.
37 /// This is handy for any kind of plugin code, where if the exception passes 77 extern "C" EXCEPTION_DISPOSITION __cdecl
38 /// through unhindered, it'll either be swallowed by an SEH exception handler 78 ExceptionBarrierReportOnlyModuleHandler(
39 /// above us on the stack, or be reported as an unhandled exception for 79 struct _EXCEPTION_RECORD* exception_record,
40 /// the application hosting the plugin code. 80 void* establisher_frame,
41 /// 81 struct _CONTEXT* context,
42 /// To use this class, simply instantiate an ExceptionBarrier just inside 82 void* reserved);
43 /// the code boundary, like this: 83
44 /// @code 84 // An alternate raw exception handler that calls out to a custom handler.
45 /// HRESULT SomeObject::SomeCOMMethod(...) { 85 // It must be declared extern "C" to match up with the SAFESEH declaration in
46 /// ExceptionBarrier report_crashes; 86 // our corresponding ASM file.
47 /// 87 extern "C" EXCEPTION_DISPOSITION __cdecl
48 /// ... other code here ... 88 ExceptionBarrierCallCustomHandler(
49 /// } 89 struct _EXCEPTION_RECORD* exception_record,
50 /// @endcode 90 void* establisher_frame,
51 class ExceptionBarrier { 91 struct _CONTEXT* context,
92 void* reserved);
93
94
95 // @name These are implemented in the associated .asm file
96 // @{
97 extern "C" void WINAPI RegisterExceptionRecord(
98 EXCEPTION_REGISTRATION* registration,
99 ExceptionHandlerFunc func);
100 extern "C" void WINAPI UnregisterExceptionRecord(
101 EXCEPTION_REGISTRATION* registration);
102 // @}
103
104
105 // Traits classes for ExceptionBarrierT.
106 class EBTraitsBase {
52 public: 107 public:
53 /// Register the barrier in the SEH chain 108 static void UnregisterException(EXCEPTION_REGISTRATION* registration) {
54 ExceptionBarrier(); 109 UnregisterExceptionRecord(registration);
110 }
111 };
55 112
56 /// And unregister on destruction 113 class EBReportAllTraits : public EBTraitsBase {
57 ~ExceptionBarrier(); 114 public:
115 static void RegisterException(EXCEPTION_REGISTRATION* registration) {
116 RegisterExceptionRecord(registration, ExceptionBarrierHandler);
117 }
118 };
58 119
59 /// Signature of the handler function which gets notified when 120 class EBReportOnlyThisModuleTraits : public EBTraitsBase {
60 /// an exception propagates through a barrier. 121 public:
61 typedef void (CALLBACK *ExceptionHandler)(EXCEPTION_POINTERS *ptrs); 122 static void RegisterException(EXCEPTION_REGISTRATION* registration) {
123 RegisterExceptionRecord(registration,
124 ExceptionBarrierReportOnlyModuleHandler);
125 }
126 };
62 127
63 /// @name Accessors 128 class EBCustomHandlerTraits : public EBTraitsBase {
64 /// @{ 129 public:
65 static void set_handler(ExceptionHandler handler) { s_handler_ = handler; } 130 static void RegisterException(EXCEPTION_REGISTRATION* registration) {
66 static ExceptionHandler handler() { return s_handler_; } 131 RegisterExceptionRecord(registration,
67 /// @} 132 ExceptionBarrierCallCustomHandler);
133 }
134 };
135
136 class ExceptionBarrierConfig {
137 public:
138 // Used to globally enable or disable crash handling by ExceptionBarrierBase
139 // instances.
140 static void set_enabled(bool enabled) {
141 s_enabled_ = enabled;
142 }
143 static bool enabled() { return s_enabled_; }
144
145 // Whether crash reports are enabled.
146 static bool s_enabled_;
147 };
148
149 template <typename RegistrarTraits>
150 class ExceptionBarrierT {
151 public:
152 // Register the barrier in the SEH chain
153 ExceptionBarrierT() {
154 RegistrarTraits::RegisterException(&registration_);
155 }
156
157 // Unregister on destruction
158 virtual ~ExceptionBarrierT() {
159 RegistrarTraits::UnregisterException(&registration_);
160 }
161
162 protected:
163 // Our SEH frame
164 EXCEPTION_REGISTRATION registration_;
165 };
166
167 // This class allows for setting a custom exception handler function. The
168 // handler is shared among all instances. This class is intended to enable
169 // testing of the SEH registration.
170 template <typename RegistrarTraits>
171 class ExceptionBarrierCustomHandlerT :
172 public ExceptionBarrierT<typename RegistrarTraits> {
173 public:
174 // Signature of the handler function which gets notified when
175 // an exception propagates through a barrier.
176 typedef void (CALLBACK* CustomExceptionHandler)(EXCEPTION_POINTERS* ptrs);
177
178 // Used to set a global custom handler used by all
179 // ExceptionBarrierCustomHandler instances.
180 static void set_custom_handler(CustomExceptionHandler handler) {
181 s_custom_handler_ = handler;
182 }
183 static CustomExceptionHandler custom_handler() { return s_custom_handler_; }
68 184
69 private: 185 private:
70 /// Our SEH frame 186 static CustomExceptionHandler s_custom_handler_;
71 EXCEPTION_REGISTRATION registration_;
72
73 /// The function that gets invoked if an exception
74 /// propagates through a barrier
75 static ExceptionHandler s_handler_;
76 }; 187 };
77 188
78 /// @name These are implemented in the associated .asm file 189 // Convenience typedefs for the ExceptionBarrierT specializations.
79 /// @{ 190 typedef ExceptionBarrierT<EBReportAllTraits> ExceptionBarrier;
80 extern "C" void WINAPI RegisterExceptionRecord( 191 typedef ExceptionBarrierT<EBReportOnlyThisModuleTraits>
81 EXCEPTION_REGISTRATION *registration, 192 ExceptionBarrierReportOnlyModule;
82 ExceptionHandlerFunc func); 193 typedef ExceptionBarrierCustomHandlerT<EBCustomHandlerTraits>
83 extern "C" void WINAPI UnregisterExceptionRecord( 194 ExceptionBarrierCustomHandler;
84 EXCEPTION_REGISTRATION *registration);
85 /// @}
86
87
88 inline ExceptionBarrier::ExceptionBarrier() {
89 RegisterExceptionRecord(&registration_, ExceptionBarrierHandler);
90 }
91
92 inline ExceptionBarrier::~ExceptionBarrier() {
93 UnregisterExceptionRecord(&registration_);
94 }
95 195
96 #endif // CHROME_FRAME_EXCEPTION_BARRIER_H_ 196 #endif // CHROME_FRAME_EXCEPTION_BARRIER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698