JDK-6321448 : self-suspension with JVM-internal monitors and mutexes may not be needed
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2005-09-08
  • Updated: 2012-10-08
  • Resolved: 2006-03-25
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6
6 b77Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
<This causes JDI jtreg test
      com/sun/jdi/ReferrersTest.java
to hang.  See Comments for more info>

I'm opening this bug to track an e-mail thread between Jim, Ken
and I concerning a self-suspension deadlock. The original e-mail
message is here in the description. The various replies are in
the comments.


Hello Dan.  I am looking (again) at netbeans problem with
doing an invokeMethod in a JDI bkpt handler.
Note that they said today that they get a hang even if they
do the invoke in a different thread.  Huh?   That should work ok.

So I tried it, and sure enough, I got a hang.  But not the
same hang as discussed before when two threads are both hitting
bkpts.  In this case, the debuggee has a main that
starts a thread and then does a thread.join.
The started thread hits a bkpt and in the debugger, the bkpt handler
starts up a new thread to do the invokeMethod.

In the debuggee, this thread is hung doing a println:

----------------- t@13 -----------------
0xff31f760	___lwp_mutex_lock + 0x8
0xfe89d0b4	void Mutex::lock() + 0x148
0xfed429c4	HeapWord*CompactingPermGen::mem_allocate(unsigned) + 0x24
0xfeaf37cc	oopDesc*CollectedHeap::permanent_obj_allocate(KlassHandle,int,Thread*) + 0x48
0xfe8e30cc	instanceOopDesc*instanceKlass::allocate_permanent_instance(Thread*) + 0x64
0xfe8e7de8	Handle java_lang_String::create_tenured_from_unicode(unsigned short*,int,Thread*) + 0x2c
0xfe9a4b10	oopDesc*StringTable::basic_add(int,Handle,unsigned short*,int,unsigned,Thread*) + 0x6c
0xfed8d92c	oopDesc*StringTable::intern(Handle,unsigned short*,int,Thread*) + 0x108
0xfe8e4a08	oopDesc*StringTable::intern(symbolOopDesc*,Thread*) + 0x40
0xfe8e3284	oopDesc*constantPoolOopDesc::string_at_impl(constantPoolHandle,int,Thread*) + 0x80
0xfeb68d6c	void InterpreterRuntime::ldc(JavaThread*,bool) + 0x168
0xfc414df4	* InvokeBreakpointTarg.invokee() bci:3 line:45 (Interpreted frame)

It is waiting for the Heap_lock.
The main thread is hung here doing the Thread.join:

0xff31f7d8	___lwp_cond_wait + 0x4
0xfed18720	bool Monitor::wait(bool,long) + 0x13c
0xfed29890	int os::pd_self_suspend_thread(Thread*) + 0xc
0xfed9d598	int JavaThread::java_suspend_self() + 0xc4
0xfed18d48	bool Monitor::wait(bool,long) + 0x764
0xfe9984ac	void VMThread::execute(VM_Operation*) + 0x1b0
0xfeaa2d70	BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle,bool,Thread*) + 0xa8
0xfe99e2c4	void ObjectSynchronizer::wait(Handle,long long,Thread*) + 0x50
0xfe99e048	JVM_MonitorWait + 0x294
0xfc4134fc	* java.lang.Object.wait(long) bci:134425908 (Interpreted frame)
0xfc4134a8	* java.lang.Object.wait(long) bci:0 (Interpreted frame)
0xfc4057e8	* java.lang.Thread.join(long) bci:38 line:1111 (Interpreted frame)
0xfc4057e8	* java.lang.Thread.join() bci:2 line:1164 (Interpreted frame)
0xfc4057e8	* InvokeBreakpointTarg.main(java.lang.String[]) bci:43 line:39 (Interpreted frame)
0xfc40021c	<StubRoutines>
0xfe8f78a0	void JavaCalls::call_helper(JavaValue*,methodHandle*,JavaCallArguments*,Thread*) + 0x1e0
0xfe9b74e8	jni_CallStaticVoidMethod + 0x500
0x00013220	main + 0x1d10

It owns the Heap_lock and is trying to do a VM op to do the revoke.

Recall that this is the same intermittent hang we saw for
jtreg InstancesTest.java for a few nightlys.

The VMThread::execute is calling wait (I don't know why) and wait, in
mutex_solaris.cpp is doing this:

      // were we externally suspended while we were waiting?
      if (jt->handle_special_suspend_equivalent_condition()) {
        //
	// Our event wait has finished and we own the _Lock_Event, but
	// while we were waiting another thread suspended us. We don't
	// want to hold the _Lock_Event while suspended because that
	// would surprise the thread that suspended us.
        //
        _Lock_Event->unlock();
        jt->java_suspend_self();
        _Lock_Event->lock();
      }

which Ken says this is a no-no and should be deleted (and ditto for
similar code in the other pd files).
Should we open a bug on this and have you fix it?


Thanks
- jjh

Comments
EVALUATION As part of my testing for Jim's fix for this problem, I ran my Suspend/Resume Stress kit for 24 hours (12 hours C1 and 12 hours for C2) and saw a grand total of two Java2Demo failures. The failures were unrelated to the suspend/resume mechanism and I believe that sets a new all time low for failures observed by that kit.
15-03-2006

SUGGESTED FIX See attached 6321448.tar file for Jim's webrev of the proposed fix.
10-03-2006

EVALUATION Allowing JVM-internal monitors and mutexes to be acquired by an externally suspended thread will be risky. The SuspendThread() APIs have two invariants upon return to the caller: 1) the _external_suspend flag is true 2) the target thread will not execute any more bytecodes or bytecode equivalents By allowing the target thread to acquire a JVM-internal monitor or mutex, the second invariant may be broken in a way that is observable by the suspend requesting thread. Changing this part of the suspend/resume mechanism will require considerable testing to ensure that new deadlocks are not introduced.
04-10-2005