Merge "Invoke all other registered handlers only for generated code"
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc
index 52ccbee..5345b89 100644
--- a/runtime/fault_handler.cc
+++ b/runtime/fault_handler.cc
@@ -146,43 +146,13 @@
}
}
-void FaultManager::HandleFault(int sig, siginfo_t* info, void* context) {
- // BE CAREFUL ALLOCATING HERE INCLUDING USING LOG(...)
- //
- // If malloc calls abort, it will be holding its lock.
- // If the handler tries to call malloc, it will deadlock.
- VLOG(signals) << "Handling fault";
- if (IsInGeneratedCode(info, context, true)) {
- VLOG(signals) << "in generated code, looking for handler";
- for (const auto& handler : generated_code_handlers_) {
- VLOG(signals) << "invoking Action on handler " << handler;
- if (handler->Action(sig, info, context)) {
-#ifdef TEST_NESTED_SIGNAL
- // In test mode we want to fall through to stack trace handler
- // on every signal (in reality this will cause a crash on the first
- // signal).
- break;
-#else
- // We have handled a signal so it's time to return from the
- // signal handler to the appropriate place.
- return;
-#endif
- }
- }
- }
-
- // We hit a signal we didn't handle. This might be something for which
- // we can give more information about so call all registered handlers to see
- // if it is.
-
+bool FaultManager::HandleFaultByOtherHandlers(int sig, siginfo_t* info, void* context) {
Thread* self = Thread::Current();
- // If ART is not running, or the thread is not attached to ART pass the
- // signal on to the next handler in the chain.
- if (self == nullptr || Runtime::Current() == nullptr || !Runtime::Current()->IsStarted()) {
- InvokeUserSignalHandler(sig, info, context);
- return;
- }
+ DCHECK(self != nullptr);
+ DCHECK(Runtime::Current() != nullptr);
+ DCHECK(Runtime::Current()->IsStarted());
+
// Now set up the nested signal handler.
// TODO: add SIGSEGV back to the nested signals when we can handle running out stack gracefully.
@@ -231,6 +201,7 @@
break;
}
}
+
if (success) {
// Save the current state and call the handlers. If anything causes a signal
// our nested signal handler will be invoked and this will longjmp to the saved
@@ -247,7 +218,7 @@
}
}
fault_manager.Init();
- return;
+ return true;
}
}
} else {
@@ -265,6 +236,40 @@
// Now put the fault manager back in place.
fault_manager.Init();
+ return false;
+}
+
+void FaultManager::HandleFault(int sig, siginfo_t* info, void* context) {
+ // BE CAREFUL ALLOCATING HERE INCLUDING USING LOG(...)
+ //
+ // If malloc calls abort, it will be holding its lock.
+ // If the handler tries to call malloc, it will deadlock.
+ VLOG(signals) << "Handling fault";
+ if (IsInGeneratedCode(info, context, true)) {
+ VLOG(signals) << "in generated code, looking for handler";
+ for (const auto& handler : generated_code_handlers_) {
+ VLOG(signals) << "invoking Action on handler " << handler;
+ if (handler->Action(sig, info, context)) {
+#ifdef TEST_NESTED_SIGNAL
+ // In test mode we want to fall through to stack trace handler
+ // on every signal (in reality this will cause a crash on the first
+ // signal).
+ break;
+#else
+ // We have handled a signal so it's time to return from the
+ // signal handler to the appropriate place.
+ return;
+#endif
+ }
+ }
+
+ // We hit a signal we didn't handle. This might be something for which
+ // we can give more information about so call all registered handlers to see
+ // if it is.
+ if (HandleFaultByOtherHandlers(sig, info, context)) {
+ return;
+ }
+ }
// Set a breakpoint in this function to catch unhandled signals.
art_sigsegv_fault();
diff --git a/runtime/fault_handler.h b/runtime/fault_handler.h
index 3b03a14..625b1e8 100644
--- a/runtime/fault_handler.h
+++ b/runtime/fault_handler.h
@@ -62,6 +62,10 @@
NO_THREAD_SAFETY_ANALYSIS;
private:
+ // The HandleFaultByOtherHandlers function is only called by HandleFault function for generated code.
+ bool HandleFaultByOtherHandlers(int sig, siginfo_t* info, void* context)
+ NO_THREAD_SAFETY_ANALYSIS;
+
std::vector<FaultHandler*> generated_code_handlers_;
std::vector<FaultHandler*> other_handlers_;
struct sigaction oldaction_;