Index: base/mac/call_with_eh_frame.cc |
diff --git a/base/mac/call_with_eh_frame.cc b/base/mac/call_with_eh_frame.cc |
index 7267676d666ff853665c8498ac54dce62ef41938..4578541419408e99eff73a06b7957dcd89c9aa7a 100644 |
--- a/base/mac/call_with_eh_frame.cc |
+++ b/base/mac/call_with_eh_frame.cc |
@@ -12,27 +12,43 @@ |
namespace base { |
namespace mac { |
+#if defined(OS_IOS) |
+// No iOS assembly implementation exists, so just call the block directly. |
+void CallWithEHFrame(void (^block)(void)) { |
+ block(); |
+} |
+#else // OS_MACOSX |
+extern "C" _Unwind_Reason_Code __gxx_personality_v0(int, |
+ _Unwind_Action, |
+ uint64_t, |
+ struct _Unwind_Exception*, |
+ struct _Unwind_Context*); |
+ |
_Unwind_Reason_Code CxxPersonalityRoutine( |
int version, |
_Unwind_Action actions, |
- uint64_t exceptionClass, |
- struct _Unwind_Exception* exceptionObject, |
+ uint64_t exception_class, |
+ struct _Unwind_Exception* exception_object, |
struct _Unwind_Context* context) { |
- // Tell libunwind that this is the end of the stack. When it encounters the |
- // CallWithEHFrame, it will stop searching for an exception handler. The |
- // result is that no exception handler has been found higher on the stack, |
- // and any that are lower on the stack (e.g. in CFRunLoopRunSpecific), will |
- // now be skipped. Since this is reporting the end of the stack, and no |
- // exception handler will have been found, std::terminate() will be called. |
- return _URC_END_OF_STACK; |
-} |
+ // Unwinding is a two-phase process: phase one searches for an exception |
+ // handler, and phase two performs cleanup. For phase one, this custom |
+ // personality will terminate the search. For phase two, this should delegate |
+ // back to the standard personality routine. |
-#if defined(OS_IOS) |
-// No iOS assembly implementation exists, so just call the block directly. |
-void CallWithEHFrame(void (^block)(void)) { |
- block(); |
+ if ((actions & _UA_SEARCH_PHASE) != 0) { |
+ // Tell libunwind that this is the end of the stack. When it encounters the |
+ // CallWithEHFrame, it will stop searching for an exception handler. The |
+ // result is that no exception handler has been found higher on the stack, |
+ // and any that are lower on the stack (e.g. in CFRunLoopRunSpecific), will |
+ // now be skipped. Since this is reporting the end of the stack, and no |
+ // exception handler will have been found, std::terminate() will be called. |
+ return _URC_END_OF_STACK; |
+ } |
+ |
+ return __gxx_personality_v0(version, actions, exception_class, |
+ exception_object, context); |
} |
-#endif |
+#endif // defined(OS_IOS) |
} // namespace mac |
} // namespace base |