diff options
author | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-01 02:10:06 +0000 |
---|---|---|
committer | robertshield@chromium.org <robertshield@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-01 02:10:06 +0000 |
commit | 72354315dd3c9682370ee2eea62446b7e5539990 (patch) | |
tree | 4f8be23e6d8ec76c7d537ca693815a7405cf2f02 /chrome_frame/exception_barrier.h | |
parent | c96c3c973c12f552ed6abd565fd326c32c227a5f (diff) | |
download | chromium_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.h | 234 |
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(®istration_); + } + + // Unregister on destruction + virtual ~ExceptionBarrierT() { + RegistrarTraits::UnregisterException(®istration_); + } + + 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(®istration_, ExceptionBarrierHandler); -} + private: + static CustomExceptionHandler s_custom_handler_; +}; -inline ExceptionBarrier::~ExceptionBarrier() { - UnregisterExceptionRecord(®istration_); -} +// Convenience typedefs for the ExceptionBarrierT specializations. +typedef ExceptionBarrierT<EBReportAllTraits> ExceptionBarrier; +typedef ExceptionBarrierT<EBReportOnlyThisModuleTraits> + ExceptionBarrierReportOnlyModule; +typedef ExceptionBarrierCustomHandlerT<EBCustomHandlerTraits> + ExceptionBarrierCustomHandler; #endif // CHROME_FRAME_EXCEPTION_BARRIER_H_ |