United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4822846 AsyncGetCallTrace: guarantee(get_thread() == thread, "must be the same thread...
JDK-4822846 : AsyncGetCallTrace: guarantee(get_thread() == thread, "must be the same thread...

Details
Type:
Bug
Submit Date:
2003-02-24
Status:
Resolved
Updated Date:
2003-07-18
Project Name:
JDK
Resolved Date:
2003-06-05
Component:
vm-legacy
OS:
solaris_8
Sub-Component:
jvmpi
CPU:
sparc
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.4.1,1.4.2
Fixed Versions:
1.4.2_02 (02)

Related Reports
Backport:
Relates:

Sub Tasks

Description
###@###.### 2003-02-24

Stress testing of the AsyncGetCallTrace() interface has exposed an
intermittent guarantee failure:

# guarantee(get_thread() == thread, "must be the same thread, quickly")
# Error ID : src/share/vm/runtime/threadLocalStorage.cp, 66

During JNI DetachCurrentThread(), the ThreadLocalStorage reference for
exiting JavaThread is set to NULL. However, an AsyncGetCallTrace() call
causes the cached thread info to be refreshed and we fail the guarantee.
Here is a partial stack trace:

  [29] report_fatal(file_name = 0xfefd20ca "/work/ws/hotspot/main/baseline-exp/s
rc/share/vm/runtime/threadLocalStorage.cpp", line_no = 66, format = 0xfefd2119 "
must be the same thread, quickly", ...), line 139 in "debug.cpp"
  [30] ThreadLocalStorage::set_thread(thread = (nil)), line 66 in "threadLocalSt
orage.cpp"
  [31] Thread::delete_thread_and_TLS_current(this = 0x3e440), line 88 in "thread
.cpp"
  [32] jni_DetachCurrentThread(vm = 0xff08a304), line 2501 in "jni.cpp"
  [33] main(0xffbef208, 0xffbef2a4, 0xffbef2b4, 0x28800, 0x0, 0x0), at 0x11d48

The complete stack trace for the java_g crash is attached as threads.log.335.
In this particular failure, the VM crashed will trying to print out the
message about the guarantee failure, but that does not really obscure the
original failure.

The failure reproduces with a less informative message with the java cmd:

# Error ID: 5448524541442C4F43414C33544F524147450E4350500042

The ErrorID maps to: threadLocalStorage.cpp, 66

Here is a snippet of the stack trace for the java cmd crash:

  [6] report_fatal(0xfefdbc35, 0x42, 0xfefdbc84, 0xfeff4000, 0xfa17fef0, 0x0), a
t 0xfee34a7c
  [7] ThreadLocalStorage::set_thread(0x0, 0xffffffc4, 0xff013178, 0xffff8000, 0x
7f, 0x0), at 0xfec522a4
  [8] _start(0xe3010, 0xfebf0c00, 0x0, 0x0, 0x0, 0x0), at 0xfecc5e4c

The complete stack trace for the java cmd crash is attached as threads.log.40.

                                    

Comments
PUBLIC COMMENTS

.
                                     
2004-06-10
SUGGESTED FIX

###@###.### 2003-03-12

Here is the context diff for the suggested fix:

------- src/share/vm/prims/forte.cpp -------
*** /tmp/geta25695      Wed Mar 12 16:49:01 2003
--- /tmp/getb25695      Wed Mar 12 16:49:01 2003
***************
*** 196,201 ****
--- 196,202 ----
  //
  static void forte_fill_call_trace_given_top(JavaThread* thd,
    JVMPI_CallTrace* trace, int depth, frame top_frame) {
+   ResetNoHandleMark rnhm;
  
    frame walkframe;
    methodOop method;
***************
*** 301,312 ****
  
  extern "C" {
  void AsyncGetCallTrace(JVMPI_CallTrace *trace, jint depth, void* ucontext) {
-   ResetNoHandleMark rnhm;
- 
    JavaThread* thread;
    ucontext_t* uc = (ucontext_t*) ucontext;
  
!   if (!((trace->env_id) && (thread = JavaThread::thread_from_jni_environment(trace->env_id))))  {
      trace->num_frames = 0;
      return;
    }
--- 302,314 ----
  
  extern "C" {
  void AsyncGetCallTrace(JVMPI_CallTrace *trace, jint depth, void* ucontext) {
    JavaThread* thread;
    ucontext_t* uc = (ucontext_t*) ucontext;
  
!   if (trace->env_id == NULL ||
!   (thread = JavaThread::thread_from_jni_environment(trace->env_id)) == NULL ||
!   thread->is_exiting()) {
!     // bad env_id, thread has exited or thread is exiting so return no frames
      trace->num_frames = 0;
      return;
    }
                                     
2004-06-11
EVALUATION

###@###.### 2003-02-24

AsyncGetCallTrace() creates a ResetNoHandleMark object on entry. The
constructor for this object calls JavaThread::current() which sends us
down the path of refreshing the thread cache. If we happen to receive a
SIGPROF signal at the right point in set_thread(), then we will refresh
the thread cache after set_thread() has cleared the cache entry. This
will cause the guarantee() to fail because the thread cache won't match
the current "set" value.

The ResetNoHandleMark object should not have been created so early so I
need to move it to just before it is needed.

My testing showed one more problem with JavaThreads. I needed to add a
check for JavaThread::is_exiting() to make sure that we didn't get
caught in the window between the start of JavaThread::exit() and being
taken off the threads list.
                                     
2004-06-11
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
1.4.2_02
tiger

FIXED IN:
1.4.2_02
tiger

INTEGRATED IN:
1.4.2_02
tiger
tiger-b08


                                     
2004-06-14



Hardware and Software, Engineered to Work Together