United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4998314 compute_compiled_exc_handler() called with pending exception
JDK-4998314 : compute_compiled_exc_handler() called with pending exception

Details
Type:
Bug
Submit Date:
2004-02-20
Status:
Closed
Updated Date:
2004-06-11
Project Name:
JDK
Resolved Date:
2004-04-06
Component:
hotspot
OS:
generic
Sub-Component:
compiler
CPU:
generic
Priority:
P3
Resolution:
Fixed
Affected Versions:
1.4.2_02
Fixed Versions:
1.4.2_05 (05)

Related Reports
Backport:
Backport:

Sub Tasks

Description
See comments section; RE might decide this belongs in compiler2
if code is specific to c2 (opto/runtime). Filing under hotspot/runtime_system
for initial evaluation.

                                    

Comments
SUGGESTED FIX


###@###.### 2004-03-31

Cleanup pending exceptions after exit from VM (after return from 
handle_exception_C_helper()): overwrite a processed exception 
(if it is not ThreadDeath) with a pending exception and process it
(call handle_exception_C_helper() again).

http://analemma.sfbay.sun.com/net/prt-archiver.sfbay/export2/archived_workspaces/main/c2_baseline/2004/20040329193754.kvn.4895131/workspace/webrevs/webrev-2004.03.29/index.html

src/share/vm/opto/runtime.cpp
***************
*** 1046,1057 ****
    debug_only(NoHandleMark __hm;)
    nmethod* nm = NULL;
    address handler_address = NULL;
!   {
      // Enter the VM 
  
      ResetNoHandleMark rnhm;
      handler_address = handle_exception_C_helper(thread, nm);
!   }
    // Back in java: Use no oops, DON'T safepoint
  
    // Now check to see if the handler we are returning is in a now
--- 1046,1070 ----
    debug_only(NoHandleMark __hm;)
    nmethod* nm = NULL;
    address handler_address = NULL;
!   bool overwrite_exception = false;
!   do {
      // Enter the VM 
  
      ResetNoHandleMark rnhm;
      handler_address = handle_exception_C_helper(thread, nm);
!     overwrite_exception = false;
!     if (thread->has_pending_exception()) { 
!       // A pending exception could be created during exit from VM (4998314).
!       // If a processed exception is not ThreadDeath overwrite it with 
!       // the pending exception and process it.
!       if (!thread->exception_oop()->is_a(SystemDictionary::threaddeath_klass())) {
!         thread->set_exception_oop(thread->pending_exception());
!         overwrite_exception = true;
!       }
!       thread->clear_pending_exception(); // Cleanup a pending exception.
!     }
!   } while (overwrite_exception);
! 
    // Back in java: Use no oops, DON'T safepoint
  
    // Now check to see if the handler we are returning is in a now
                                     
2004-07-08
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
1.4.2_05
generic
tiger-beta2

FIXED IN:
1.4.2_05
tiger-beta2

INTEGRATED IN:
1.4.2_05
tiger-b46
tiger-beta2

VERIFIED IN:
1.4.2_05


                                     
2004-07-08
EVALUATION

From looking at this in the SA I believe the what occurs is this.  A thread is has the following call stack

java/net/SocketInputStream.socketRead0
java/net/SocketInputStream.read([BII)I
IE/Iona/Orbix2/CORBA/SocketConnection
IE/Iona/Orbix2/CORBA/ClientConnection.run()
java/lang/Thread.run()

at least the top 2 frames are compiled.  socketRead0 is an native method, though I don't think that's required for this bug to occur.  socketRead0 returns with an exception, java.net.SocketException: Socket closed.  This is the oop at 0xd708bc38 in the core file.  The compiled native wrapper dispatches the exception correctly and eventually calls into the ExceptionBlob which calls OptoRuntime::handle_exception_C which is a JRT_ENTRY, meaning it can safepoint on it's way out of the VM.  The exception lookup code decides that it should return to the exception handler of the called compiled frame, read.  On the way out of the VM a safepoint occurs and Thread.stop() is called in another thread on this thread.  This installs an instance of java/lang/ThreadDeath in the pending async exception field.  This is oop 0xd7087d98 in the core file.  Part of the logic in JavaThread::send_thread_stop is to deoptimize the caller frame under certain conditions, namely if the last frame is a runtime stub or a safepoint blob.  In this case the last frame is the exception blob which is neither of these.  So the ThreaDeath get's installed in pending exception and we return to the compiled Java code.  C2's exception dispatch path keeps the current exception in the thread's exception_oop field.  So know the thread has both an exception the exception_oop and in the pending_exception field.  When it reenters the exception blob from SocketInputStream.read it calls compute_compiled_exc_handler which eventually dies when it installs the ExceptionMark because the pending exception is set.  So the straightforward fix is to add the exception blob to things that cause the caller frame to deopt in send_thread_stop.
###@###.### 2004-03-02

###@###.### 2004-03-23

The small test (in the comments) confirms this evaluation.
                                     
2004-03-02



Hardware and Software, Engineered to Work Together