OSDN Git Service

Register signal handler to kernel if not claimed
authorjgu21 <jinghui.gu@intel.com>
Fri, 24 Jul 2015 05:40:33 +0000 (13:40 +0800)
committerjgu21 <jinghui.gu@intel.com>
Sat, 25 Jul 2015 12:15:52 +0000 (20:15 +0800)
To set special handler for a signal, if the signal was not
claimed before, the default handler in sigchain must be registerred
for it before claimimg it in sigchain.

Change-Id: I7ab74392cabb7f34af8ae038c90d20f0641b9d99
Signed-off-by: jgu21 <jinghui.gu@intel.com>
sigchainlib/sigchain.cc
test/115-native-bridge/expected.txt
test/115-native-bridge/nativebridge.cc

index 1391d14..8e9d421 100644 (file)
@@ -337,14 +337,16 @@ extern "C" void SetSpecialSignalHandlerFn(int signal, SpecialSignalHandlerFn fn)
   // In case the chain isn't claimed, claim it for ourself so we can ensure the managed handler
   // goes first.
   if (!user_sigactions[signal].IsClaimed()) {
-    struct sigaction tmp;
-    tmp.sa_sigaction = sigchainlib_managed_handler_sigaction;
-    sigemptyset(&tmp.sa_mask);
-    tmp.sa_flags = SA_SIGINFO | SA_ONSTACK;
+    struct sigaction act, old_act;
+    act.sa_sigaction = sigchainlib_managed_handler_sigaction;
+    sigemptyset(&act.sa_mask);
+    act.sa_flags = SA_SIGINFO | SA_ONSTACK;
 #if !defined(__APPLE__) && !defined(__mips__)
-    tmp.sa_restorer = nullptr;
+    act.sa_restorer = nullptr;
 #endif
-    user_sigactions[signal].Claim(tmp);
+    if (sigaction(signal, &act, &old_act) != -1) {
+      user_sigactions[signal].Claim(old_act);
+    }
   }
 }
 
index 464d2c8..372ecd0 100644 (file)
@@ -61,3 +61,4 @@ Getting trampoline for Java_Main_testNewStringObject with shorty V.
 trampoline_Java_Main_testNewStringObject called!
 Getting trampoline for Java_Main_testSignal with shorty I.
 NB signal handler with signal 11.
+NB signal handler with signal 4.
index c8141a7..a6a6e08 100644 (file)
@@ -200,8 +200,9 @@ static jint trampoline_Java_Main_testSignal(JNIEnv*, jclass) {
 #if !defined(__APPLE__) && !defined(__mips__)
   tmp.sa_restorer = nullptr;
 #endif
-  sigaction(SIGSEGV, &tmp, nullptr);
 
+  // Test segv
+  sigaction(SIGSEGV, &tmp, nullptr);
 #if defined(__arm__) || defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
   // On supported architectures we cause a real SEGV.
   *go_away_compiler = 'a';
@@ -209,6 +210,11 @@ static jint trampoline_Java_Main_testSignal(JNIEnv*, jclass) {
   // On other architectures we simulate SEGV.
   kill(getpid(), SIGSEGV);
 #endif
+
+  // Test sigill
+  sigaction(SIGILL, &tmp, nullptr);
+  kill(getpid(), SIGILL);
+
   return 1234;
 }
 
@@ -385,27 +391,29 @@ extern "C" bool nb_is_compatible(uint32_t bridge_version ATTRIBUTE_UNUSED) {
 // 004-SignalTest.
 static bool nb_signalhandler(int sig, siginfo_t* info ATTRIBUTE_UNUSED, void* context) {
   printf("NB signal handler with signal %d.\n", sig);
+  if (sig == SIGSEGV) {
 #if defined(__arm__)
-  struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
-  struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
-  sc->arm_pc += 2;          // Skip instruction causing segv.
+    struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
+    struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
+    sc->arm_pc += 2;          // Skip instruction causing segv & sigill.
 #elif defined(__aarch64__)
-  struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
-  struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
-  sc->pc += 4;          // Skip instruction causing segv.
+    struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
+    struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
+    sc->pc += 4;          // Skip instruction causing segv & sigill.
 #elif defined(__i386__) || defined(__x86_64__)
-  struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
-  uc->CTX_EIP += 3;
+    struct ucontext *uc = reinterpret_cast<struct ucontext*>(context);
+    uc->CTX_EIP += 3;
 #else
-  UNUSED(context);
+    UNUSED(context);
 #endif
+  }
   // We handled this...
   return true;
 }
 
 static ::android::NativeBridgeSignalHandlerFn native_bridge_get_signal_handler(int signal) {
-  // Only test segfault handler.
-  if (signal == SIGSEGV) {
+  // Test segv for already claimed signal, and sigill for not claimed signal
+  if ((signal == SIGSEGV) || (signal == SIGILL)) {
     return &nb_signalhandler;
   }
   return nullptr;