United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 6814943 getcpool001 catches more than one JvmtiThreadState problem
6814943 : getcpool001 catches more than one JvmtiThreadState problem

Details
Type:
Bug
Submit Date:
2009-03-09
Status:
Closed
Updated Date:
2012-02-01
Project Name:
JDK
Resolved Date:
2011-03-08
Component:
hotspot
OS:
generic
Sub-Component:
jvmti
CPU:
generic
Priority:
P2
Resolution:
Fixed
Affected Versions:
hs14,hs15,hs19
Fixed Versions:
hs20

Related Reports
Backport:
Backport:
Relates:

Sub Tasks

Description
Even with the fix for 6700114 in place, the getcpool001 test continues
to fail. It fails less frequently now, but it still fails. I've verified
that the fix is in place in the HSX-14-B12 bits and in RT_Baseline after
I pushed the fix for 6700114 for HSX-15-B03. It looks like the test
catches more than one problem on almost identical code paths and I didn't
fix the second code path.

Here is my nightly analysis entry:

New nsk.jvmti failures (from 2009.03.04)
    nsk/jvmti/unit/GetConstantPool/getcpool001
        This test failed the following assertion on Solaris SPARC
        Server VM -Xcomp (machine denab):

            Internal Error (src/share/vm/prims/jvmtiThreadState.cpp:203)
            Error: assert(_thread->get_interp_only_mode() == 1,
                "leaving interp only when mode not one")

        This failure mode is covered by the following bug:

            6700114 3/4 Assertion (_thread->get_interp_only_mode() == 1,
                        "leaving interp only when mode not one")

        This bug is in state "fix available" and the fix is included in
        the bits being tested by this nightly.
http://sqeweb.sfbay/nfs/tools/gtee/results/JDK7/NIGHTLY/VM/2010-07-30/G1_GC_Baseline/vm/solaris-i586/client/mixed/solaris-i586_vm_client_mixed_nsk.jvmti.unit.testlist/ResultDir/getcpool001//hs_err_pid15974.log

nsk/jvmti/unit/GetConstantPool/getcpool001
nsk.jvmti.unit.GetConstantPool.getcpool001

                                    

Comments
EVALUATION

http://hg.openjdk.java.net/jdk7/hotspot/hotspot/rev/db2b0f8c1cef
                                     
2011-01-14
EVALUATION

Better solution (suggested by David Holmes):  Take the JvmtiThreadState_lock before accessing the JavaThread::_jvmti_thread_state field or calling JvmtiEventController::thread_ended().
                                     
2011-01-11
EVALUATION

http://hg.openjdk.java.net/jdk7/hotspot-rt/hotspot/rev/db2b0f8c1cef
                                     
2011-01-11
EVALUATION

There is a race condition in JvmtiThreadState::state_for_while_locked() and ~JavaThread().   In state_for_while_locked(), we check the terminated state of the Thread and if it is not exiting, we create the JvmtiThreadState and record it in JavaThread::_jvmti_thread_state.  In ~JavaThread(), we set the _terminated field to exiting, and then check _jvmti_thread_state to see if the JvmtiThreadState object needs to be deallocated.  There is no common lock code between the two, so it is possible for state_for_while_locked() to see a non-exited thread state, but then the entirety of ~JavaThread() may run in another thread before the JvmtiThreadState is created and set in the JavaThread::_jvmti_thread_state field.  In that case we end up with a live JvmtiThreadState that refers to a dead thread (as the check of _jvmti_thread_state in ~JavaThread() will see NULL and not deallocate the JvmtiThreadState).

A solution that appears to work:

In JvmtiThreadState::state_for_while_locked(), create the state unconditionally if it does not exist, and set it in JavaThread::_jvmti_thread_state.  Then check for thread exited state and if the thread has exited,  "rollback" and delete the JavaThreadState.  Also mark the fields _jvmti_thread_state and _terminated as volatile and use memory fences to ensure that the loads and stores of those fields are visible to other threads.
                                     
2011-01-07



Hardware and Software, Engineered to Work Together