Blame SOURCES/8181419-pr3413-rh1463144.patch

045ef6
# HG changeset patch
045ef6
# User stuefe
045ef6
# Date 1497865921 -7200
045ef6
#      Mon Jun 19 11:52:01 2017 +0200
045ef6
# Node ID ca0c7b2783e0102468218589a062e7ac4736aae2
045ef6
# Parent  148a7d6c463ad1726bad8a9e8d5df191314d704b
045ef6
8181419, PR3413, RH1463144: Race in jdwp invoker handling may lead to crashes or invalid results
045ef6
Reviewed-by: sspitsyn, sgehwolf, clanger
045ef6
045ef6
diff --git a/src/share/back/invoker.c b/src/share/back/invoker.c
045ef6
--- openjdk/jdk/src/share/back/invoker.c
045ef6
+++ openjdk/jdk/src/share/back/invoker.c
045ef6
@@ -212,30 +212,6 @@
045ef6
 }
045ef6
 
045ef6
 /*
045ef6
- * Delete saved global references - if any - for:
045ef6
- * - a potentially thrown Exception
045ef6
- * - a returned refernce/array value
045ef6
- * See invoker_doInvoke() and invoke* methods where global references
045ef6
- * are being saved.
045ef6
- */
045ef6
-static void
045ef6
-deletePotentiallySavedGlobalRefs(JNIEnv *env, InvokeRequest *request)
045ef6
-{
045ef6
-    /* Delete potentially saved return value */
045ef6
-    if ((request->invokeType == INVOKE_CONSTRUCTOR) ||
045ef6
-        (returnTypeTag(request->methodSignature) == JDWP_TAG(OBJECT)) ||
045ef6
-        (returnTypeTag(request->methodSignature) == JDWP_TAG(ARRAY))) {
045ef6
-        if (request->returnValue.l != NULL) {
045ef6
-            tossGlobalRef(env, &(request->returnValue.l));
045ef6
-        }
045ef6
-    }
045ef6
-    /* Delete potentially saved exception */
045ef6
-    if (request->exception != NULL) {
045ef6
-        tossGlobalRef(env, &(request->exception));
045ef6
-    }
045ef6
-}
045ef6
-
045ef6
-/*
045ef6
  * Delete global argument references from the request which got put there before a
045ef6
  * invoke request was carried out. See fillInvokeRequest().
045ef6
  */
045ef6
@@ -744,6 +720,7 @@
045ef6
     jint id;
045ef6
     InvokeRequest *request;
045ef6
     jboolean detached;
045ef6
+    jboolean mustReleaseReturnValue = JNI_FALSE;
045ef6
 
045ef6
     JDI_ASSERT(thread);
045ef6
 
045ef6
@@ -787,6 +764,13 @@
045ef6
         id = request->id;
045ef6
         exc = request->exception;
045ef6
         returnValue = request->returnValue;
045ef6
+
045ef6
+        /* Release return value and exception references, but delay the release
045ef6
+         * until after the return packet was sent. */
045ef6
+        mustReleaseReturnValue = request->invokeType == INVOKE_CONSTRUCTOR ||
045ef6
+           returnTypeTag(request->methodSignature) == JDWP_TAG(OBJECT) ||
045ef6
+           returnTypeTag(request->methodSignature) == JDWP_TAG(ARRAY);
045ef6
+
045ef6
     }
045ef6
 
045ef6
     /*
045ef6
@@ -801,6 +785,12 @@
045ef6
      */
045ef6
     deleteGlobalArgumentRefs(env, request);
045ef6
 
045ef6
+    /* From now on, do not access the request structure anymore
045ef6
+     * for this request id, because once we give up the invokerLock it may
045ef6
+     * be immediately reused by a new invoke request.
045ef6
+     */
045ef6
+    request = NULL;
045ef6
+
045ef6
     /*
045ef6
      * Give up the lock before I/O operation
045ef6
      */
045ef6
@@ -821,7 +811,12 @@
045ef6
      */
045ef6
     eventHandler_lock(); // for proper lock order
045ef6
     debugMonitorEnter(invokerLock);
045ef6
-    deletePotentiallySavedGlobalRefs(env, request);
045ef6
+    if (mustReleaseReturnValue && returnValue.l != NULL) {
045ef6
+        tossGlobalRef(env, &returnValue.l);
045ef6
+    }
045ef6
+    if (exc != NULL) {
045ef6
+        tossGlobalRef(env, &exc);
045ef6
+    }
045ef6
     debugMonitorExit(invokerLock);
045ef6
     eventHandler_unlock();
045ef6
 }