diff src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp @ 107:93b6525e3b82

6603919: Stackwalking crash on x86 -server with Sun Studio's collect -j on Summary: Rewrite frame::safe_for_sender and friends to be safe for collector/analyzer Reviewed-by: dcubed, kvn
author sgoldman
date Tue, 08 Apr 2008 12:23:15 -0400
parents a61af66fc99e
children d1605aabd0a1
line wrap: on
line diff
--- a/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp	Mon Apr 07 15:15:16 2008 -0700
+++ b/src/os_cpu/solaris_x86/vm/thread_solaris_x86.cpp	Tue Apr 08 12:23:15 2008 -0400
@@ -32,49 +32,53 @@
 
   assert(Thread::current() == this, "caller must be current thread");
   assert(this->is_Java_thread(), "must be JavaThread");
-
   JavaThread* jt = (JavaThread *)this;
 
-  // If we have a last_Java_frame, then we should use it even if
-  // isInJava == true.  It should be more reliable than ucontext info.
+  // last_Java_frame is always walkable and safe use it if we have it
+
   if (jt->has_last_Java_frame()) {
     *fr_addr = jt->pd_last_frame();
     return true;
   }
 
-  // At this point, we don't have a last_Java_frame, so
-  // we try to glean some information out of the ucontext
-  // if we were running Java code when SIGPROF came in.
-  if (isInJava) {
-    ucontext_t* uc = (ucontext_t*) ucontext;
+  ucontext_t* uc = (ucontext_t*) ucontext;
 
-    intptr_t* ret_fp;
-    intptr_t* ret_sp;
-    ExtendedPC addr = os::Solaris::fetch_frame_from_ucontext(this, uc,
-      &ret_sp, &ret_fp);
-    if (addr.pc() == NULL || ret_sp == NULL ) {
-      // ucontext wasn't useful
-      return false;
-    }
+  // We always want to use the initial frame we create from the ucontext as
+  // it certainly signals where we currently are. However that frame may not
+  // be safe for calling sender. In that case if we have a last_Java_frame
+  // then the forte walker will switch to that frame as the virtual sender
+  // for the frame we create here which is not sender safe.
 
-    frame ret_frame(ret_sp, ret_fp, addr.pc());
-    if (!ret_frame.safe_for_sender(jt)) {
-#ifdef COMPILER2
-      frame ret_frame2(ret_sp, NULL, addr.pc());
-      if (!ret_frame2.safe_for_sender(jt)) {
-        // nothing else to try if the frame isn't good
-        return false;
-      }
-      ret_frame = ret_frame2;
-#else
-      // nothing else to try if the frame isn't good
-      return false;
-#endif /* COMPILER2 */
-    }
-    *fr_addr = ret_frame;
-    return true;
+  intptr_t* ret_fp;
+  intptr_t* ret_sp;
+  ExtendedPC addr = os::Solaris::fetch_frame_from_ucontext(this, uc, &ret_sp, &ret_fp);
+
+  // Something would really have to be screwed up to get a NULL pc
+
+  if (addr.pc() == NULL ) {
+    assert(false, "NULL pc from signal handler!");
+    return false;
+
   }
 
-  // nothing else to try
-  return false;
+  // If sp and fp are nonsense just leave them out
+
+  if ((address)ret_sp >= jt->stack_base() ||
+      (address)ret_sp < jt->stack_base() - jt->stack_size() ) {
+
+      ret_sp = NULL;
+      ret_fp = NULL;
+  } else {
+
+    // sp is reasonable is fp reasonable?
+    if ( (address)ret_fp >= jt->stack_base() || ret_fp < ret_sp) {
+      ret_fp = NULL;
+    }
+  }
+
+  frame ret_frame(ret_sp, ret_fp, addr.pc());
+
+  *fr_addr = ret_frame;
+  return true;
+
 }