Handle nested signals

This allows for signals to be raised inside the ART signal handler.
This can occur when the JavaStackTraceHandler attempts to generate
a stack trace and something goes wrong.

It also fixes an issue where the fault manager was not being
correctly shut down inside the signal chaining code.  In this
case the signal handler was not restored to the original.

Bug: 17006816
Bug: 17133266

(cherry picked from commit fabe91e0d558936ac26b98d2b4ee1af08f58831d)

Change-Id: I10730ef52d5d8d34610a5293253b3be6caf4829e
diff --git a/runtime/arch/arm/fault_handler_arm.cc b/runtime/arch/arm/fault_handler_arm.cc
index 28b69ec..564fcba 100644
--- a/runtime/arch/arm/fault_handler_arm.cc
+++ b/runtime/arch/arm/fault_handler_arm.cc
@@ -16,6 +16,7 @@
 
 
 #include "fault_handler.h"
+
 #include <sys/ucontext.h>
 #include "base/macros.h"
 #include "base/hex_dump.h"
@@ -46,6 +47,23 @@
   return instr_size;
 }
 
+void FaultManager::HandleNestedSignal(int sig, siginfo_t* info, void* context) {
+  // Note that in this handler we set up the registers and return to
+  // longjmp directly rather than going through an assembly language stub.  The
+  // reason for this is that longjmp is (currently) in ARM mode and that would
+  // require switching modes in the stub - incurring an unwanted relocation.
+
+  struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
+  struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
+  Thread* self = Thread::Current();
+  CHECK(self != nullptr);       // This will cause a SIGABRT if self is nullptr.
+
+  sc->arm_r0 = reinterpret_cast<uintptr_t>(*self->GetNestedSignalState());
+  sc->arm_r1 = 1;
+  sc->arm_pc = reinterpret_cast<uintptr_t>(longjmp);
+  VLOG(signals) << "longjmp address: " << reinterpret_cast<void*>(sc->arm_pc);
+}
+
 void FaultManager::GetMethodAndReturnPcAndSp(siginfo_t* siginfo, void* context,
                                              mirror::ArtMethod** out_method,
                                              uintptr_t* out_return_pc, uintptr_t* out_sp) {