summaryrefslogtreecommitdiffstats
path: root/chrome_frame/exception_barrier.h
diff options
context:
space:
mode:
authorrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-01 02:10:06 +0000
committerrobertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-01 02:10:06 +0000
commit72354315dd3c9682370ee2eea62446b7e5539990 (patch)
tree4f8be23e6d8ec76c7d537ca693815a7405cf2f02 /chrome_frame/exception_barrier.h
parentc96c3c973c12f552ed6abd565fd326c32c227a5f (diff)
downloadchromium_src-72354315dd3c9682370ee2eea62446b7e5539990.zip
chromium_src-72354315dd3c9682370ee2eea62446b7e5539990.tar.gz
chromium_src-72354315dd3c9682370ee2eea62446b7e5539990.tar.bz2
Avoid reporting crashes for exceptions that hit our SEH from calls to the original implementation of BindToStorage() when we do not wrap the bind status callback.
BUG=42660 TEST=Induce exception in code called under original IMoniker::BindToStorage implementation when we don't wrap the callback and notice that no crash is reported. Review URL: http://codereview.chromium.org/1748016 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46176 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/exception_barrier.h')
-rw-r--r--chrome_frame/exception_barrier.h234
1 files changed, 167 insertions, 67 deletions
diff --git a/chrome_frame/exception_barrier.h b/chrome_frame/exception_barrier.h
index 26cbc44..e3e5350 100644
--- a/chrome_frame/exception_barrier.h
+++ b/chrome_frame/exception_barrier.h
@@ -1,96 +1,196 @@
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-
+//
// A class to make it easy to tag exception propagation boundaries and
// get crash reports of exceptions that pass over same.
+//
+// An exception barrier is used to report exceptions that pass through
+// a boundary where exceptions shouldn't pass, such as e.g. COM interface
+// boundaries.
+// This is handy for any kind of plugin code, where if the exception passes
+// through unhindered, it'll either be swallowed by an SEH exception handler
+// above us on the stack, or be reported as an unhandled exception for
+// the application hosting the plugin code.
+//
+// IMPORTANT NOTE: This class has crash_reporting disabled by default. To
+// enable crash reporting call:
+//
+// @code
+// ExceptionBarrierBase::set_crash_handling(true)
+// @endcode
+//
+// somewhere in your initialization code.
+//
+// Then, to use this class, simply instantiate an ExceptionBarrier just inside
+// the code boundary, like this:
+// @code
+// HRESULT SomeObject::SomeCOMMethod(...) {
+// ExceptionBarrier report_crashes;
+//
+// ... other code here ...
+// }
+// @endcode
+//
+// There are three ExceptionBarrier types defined here:
+// 1) ExceptionBarrier which reports all crashes it sees.
+// 2) ExceptionBarrierReportOnlyModule which reports only crashes occurring
+// in this module.
+// 3) ExceptionBarrierCustomHandler which calls the handler set by a call
+// to ExceptionBarrierCallCustomHandler::set_custom_handler(). Note that
+// there is one custom handler for all ExceptionBarrierCallCustomHandler
+// instances. If set_custom_handler() is never called, this places an
+// SEH in the chain that just returns ExceptionContinueSearch.
+
#ifndef CHROME_FRAME_EXCEPTION_BARRIER_H_
#define CHROME_FRAME_EXCEPTION_BARRIER_H_
#include <windows.h>
-/// This is the type dictated for an exception handler by the platform ABI
-/// @see _except_handler in excpt.h
-typedef EXCEPTION_DISPOSITION (__cdecl *ExceptionHandlerFunc)(
- struct _EXCEPTION_RECORD *exception_record,
- void * establisher_frame,
- struct _CONTEXT *context,
- void * reserved);
+extern "C" IMAGE_DOS_HEADER __ImageBase;
-/// The type of an exception record in the exception handler chain
+// This is the type dictated for an exception handler by the platform ABI
+// @see _except_handler in excpt.h
+typedef EXCEPTION_DISPOSITION (__cdecl* ExceptionHandlerFunc)(
+ struct _EXCEPTION_RECORD* exception_record,
+ void* establisher_frame,
+ struct _CONTEXT* context,
+ void* reserved);
+
+// The type of an exception record in the exception handler chain
struct EXCEPTION_REGISTRATION {
- EXCEPTION_REGISTRATION *prev;
+ EXCEPTION_REGISTRATION* prev;
ExceptionHandlerFunc handler;
};
-/// This is our raw exception handler, it must be declared extern "C" to
-/// match up with the SAFESEH declaration in our corresponding ASM file
+// This is our raw exception handler, it must be declared extern "C" to
+// match up with the SAFESEH declaration in our corresponding ASM file.
+extern "C" EXCEPTION_DISPOSITION __cdecl
+ExceptionBarrierHandler(struct _EXCEPTION_RECORD* exception_record,
+ void* establisher_frame,
+ struct _CONTEXT* context,
+ void* reserved);
+
+// An alternate raw exception handler that reports crashes only for the current
+// module. It must be declared extern "C" to match up with the SAFESEH
+// declaration in our corresponding ASM file.
extern "C" EXCEPTION_DISPOSITION __cdecl
-ExceptionBarrierHandler(struct _EXCEPTION_RECORD *exception_record,
- void * establisher_frame,
- struct _CONTEXT *context,
- void * reserved);
-
-/// An exception barrier is used to report exceptions that pass through
-/// a boundary where exceptions shouldn't pass, such as e.g. COM interface
-/// boundaries.
-/// This is handy for any kind of plugin code, where if the exception passes
-/// through unhindered, it'll either be swallowed by an SEH exception handler
-/// above us on the stack, or be reported as an unhandled exception for
-/// the application hosting the plugin code.
-///
-/// To use this class, simply instantiate an ExceptionBarrier just inside
-/// the code boundary, like this:
-/// @code
-/// HRESULT SomeObject::SomeCOMMethod(...) {
-/// ExceptionBarrier report_crashes;
-///
-/// ... other code here ...
-/// }
-/// @endcode
-class ExceptionBarrier {
+ExceptionBarrierReportOnlyModuleHandler(
+ struct _EXCEPTION_RECORD* exception_record,
+ void* establisher_frame,
+ struct _CONTEXT* context,
+ void* reserved);
+
+// An alternate raw exception handler that calls out to a custom handler.
+// It must be declared extern "C" to match up with the SAFESEH declaration in
+// our corresponding ASM file.
+extern "C" EXCEPTION_DISPOSITION __cdecl
+ExceptionBarrierCallCustomHandler(
+ struct _EXCEPTION_RECORD* exception_record,
+ void* establisher_frame,
+ struct _CONTEXT* context,
+ void* reserved);
+
+
+// @name These are implemented in the associated .asm file
+// @{
+extern "C" void WINAPI RegisterExceptionRecord(
+ EXCEPTION_REGISTRATION* registration,
+ ExceptionHandlerFunc func);
+extern "C" void WINAPI UnregisterExceptionRecord(
+ EXCEPTION_REGISTRATION* registration);
+// @}
+
+
+// Traits classes for ExceptionBarrierT.
+class EBTraitsBase {
public:
- /// Register the barrier in the SEH chain
- ExceptionBarrier();
+ static void UnregisterException(EXCEPTION_REGISTRATION* registration) {
+ UnregisterExceptionRecord(registration);
+ }
+};
- /// And unregister on destruction
- ~ExceptionBarrier();
+class EBReportAllTraits : public EBTraitsBase {
+ public:
+ static void RegisterException(EXCEPTION_REGISTRATION* registration) {
+ RegisterExceptionRecord(registration, ExceptionBarrierHandler);
+ }
+};
- /// Signature of the handler function which gets notified when
- /// an exception propagates through a barrier.
- typedef void (CALLBACK *ExceptionHandler)(EXCEPTION_POINTERS *ptrs);
+class EBReportOnlyThisModuleTraits : public EBTraitsBase {
+ public:
+ static void RegisterException(EXCEPTION_REGISTRATION* registration) {
+ RegisterExceptionRecord(registration,
+ ExceptionBarrierReportOnlyModuleHandler);
+ }
+};
- /// @name Accessors
- /// @{
- static void set_handler(ExceptionHandler handler) { s_handler_ = handler; }
- static ExceptionHandler handler() { return s_handler_; }
- /// @}
+class EBCustomHandlerTraits : public EBTraitsBase {
+ public:
+ static void RegisterException(EXCEPTION_REGISTRATION* registration) {
+ RegisterExceptionRecord(registration,
+ ExceptionBarrierCallCustomHandler);
+ }
+};
- private:
- /// Our SEH frame
- EXCEPTION_REGISTRATION registration_;
+class ExceptionBarrierConfig {
+ public:
+ // Used to globally enable or disable crash handling by ExceptionBarrierBase
+ // instances.
+ static void set_enabled(bool enabled) {
+ s_enabled_ = enabled;
+ }
+ static bool enabled() { return s_enabled_; }
+
+ // Whether crash reports are enabled.
+ static bool s_enabled_;
+};
- /// The function that gets invoked if an exception
- /// propagates through a barrier
- static ExceptionHandler s_handler_;
+template <typename RegistrarTraits>
+class ExceptionBarrierT {
+ public:
+ // Register the barrier in the SEH chain
+ ExceptionBarrierT() {
+ RegistrarTraits::RegisterException(&registration_);
+ }
+
+ // Unregister on destruction
+ virtual ~ExceptionBarrierT() {
+ RegistrarTraits::UnregisterException(&registration_);
+ }
+
+ protected:
+ // Our SEH frame
+ EXCEPTION_REGISTRATION registration_;
};
-/// @name These are implemented in the associated .asm file
-/// @{
-extern "C" void WINAPI RegisterExceptionRecord(
- EXCEPTION_REGISTRATION *registration,
- ExceptionHandlerFunc func);
-extern "C" void WINAPI UnregisterExceptionRecord(
- EXCEPTION_REGISTRATION *registration);
-/// @}
+// This class allows for setting a custom exception handler function. The
+// handler is shared among all instances. This class is intended to enable
+// testing of the SEH registration.
+template <typename RegistrarTraits>
+class ExceptionBarrierCustomHandlerT :
+ public ExceptionBarrierT<typename RegistrarTraits> {
+ public:
+ // Signature of the handler function which gets notified when
+ // an exception propagates through a barrier.
+ typedef void (CALLBACK* CustomExceptionHandler)(EXCEPTION_POINTERS* ptrs);
+ // Used to set a global custom handler used by all
+ // ExceptionBarrierCustomHandler instances.
+ static void set_custom_handler(CustomExceptionHandler handler) {
+ s_custom_handler_ = handler;
+ }
+ static CustomExceptionHandler custom_handler() { return s_custom_handler_; }
-inline ExceptionBarrier::ExceptionBarrier() {
- RegisterExceptionRecord(&registration_, ExceptionBarrierHandler);
-}
+ private:
+ static CustomExceptionHandler s_custom_handler_;
+};
-inline ExceptionBarrier::~ExceptionBarrier() {
- UnregisterExceptionRecord(&registration_);
-}
+// Convenience typedefs for the ExceptionBarrierT specializations.
+typedef ExceptionBarrierT<EBReportAllTraits> ExceptionBarrier;
+typedef ExceptionBarrierT<EBReportOnlyThisModuleTraits>
+ ExceptionBarrierReportOnlyModule;
+typedef ExceptionBarrierCustomHandlerT<EBCustomHandlerTraits>
+ ExceptionBarrierCustomHandler;
#endif // CHROME_FRAME_EXCEPTION_BARRIER_H_