changeset 1749:060c4c7082ef

6529758: JVMTI Waiters demo crashes. Double free. Reviewed-by: ohair, tbell
author alanb
date Mon, 14 Sep 2009 15:29:13 +0100
parents 020a0fed38c9
children aac01ec2cec4
files src/share/demo/jvmti/waiters/Agent.cpp src/share/demo/jvmti/waiters/Agent.hpp src/share/demo/jvmti/waiters/Monitor.cpp src/share/demo/jvmti/waiters/Monitor.hpp
diffstat 4 files changed, 52 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/demo/jvmti/waiters/Agent.cpp	Sat Sep 12 15:30:13 2009 -0700
+++ b/src/share/demo/jvmti/waiters/Agent.cpp	Mon Sep 14 15:29:13 2009 +0100
@@ -72,36 +72,30 @@
 {
     jvmtiError err;
     Monitor   *m;
+    jlong      tag;
 
-    /* We use tags to track these, the tag is the Monitor pointer */
-    err = jvmti->RawMonitorEnter(lock); {
-        check_jvmti_error(jvmti, err, "raw monitor enter");
-
-        /* The raw monitor enter/exit protects us from creating two
-         *   instances for the same object.
-         */
-        jlong tag;
-
-        m   = NULL;
-        tag = (jlong)0;
-        err = jvmti->GetTag(object, &tag);
-        check_jvmti_error(jvmti, err, "get tag");
+    m   = NULL;
+    tag = (jlong)0;
+    err = jvmti->GetTag(object, &tag);
+    check_jvmti_error(jvmti, err, "get tag");
+    /*LINTED*/
+    m = (Monitor *)(void *)(ptrdiff_t)tag;
+    if ( m == NULL ) {
+        m = new Monitor(jvmti, env, object);
+        /* Save monitor on list */
+        if (monitor_count == monitor_list_size) {
+            monitor_list_size += monitor_list_grow_size;
+            monitor_list = (Monitor**)realloc((void*)monitor_list,
+                (monitor_list_size)*(int)sizeof(Monitor*));
+        }
+        monitor_list[monitor_count] = m;
+        m->set_slot(monitor_count);
+        monitor_count++;
         /*LINTED*/
-        m = (Monitor *)(void *)(ptrdiff_t)tag;
-        if ( m == NULL ) {
-            m = new Monitor(jvmti, env, object);
-            /*LINTED*/
-            tag = (jlong)(ptrdiff_t)(void *)m;
-            err = jvmti->SetTag(object, tag);
-            check_jvmti_error(jvmti, err, "set tag");
-            /* Save monitor on list */
-            monitor_list = (Monitor**)realloc((void*)monitor_list,
-                                (monitor_count+1)*(int)sizeof(Monitor*));
-            monitor_list[monitor_count++] = m;
-        }
-    } err = jvmti->RawMonitorExit(lock);
-    check_jvmti_error(jvmti, err, "raw monitor exit");
-
+        tag = (jlong)(ptrdiff_t)(void *)m;
+        err = jvmti->SetTag(object, tag);
+        check_jvmti_error(jvmti, err, "set tag");
+    }
     return m;
 }
 
@@ -112,12 +106,11 @@
 
     stdout_message("Agent created..\n");
     stdout_message("VMInit...\n");
-    /* Create a Monitor lock to use */
-    err = jvmti->CreateRawMonitor("waiters Agent lock", &lock);
-    check_jvmti_error(jvmti, err, "create raw monitor");
     /* Start monitor list */
     monitor_count = 0;
-    monitor_list  = (Monitor**)malloc((int)sizeof(Monitor*));
+    monitor_list_size = initial_monitor_list_size;
+    monitor_list = (Monitor**)
+        malloc(monitor_list_size*(int)sizeof(Monitor*));
 }
 
 Agent::~Agent()
@@ -134,9 +127,6 @@
         delete monitor_list[i];
     }
     free(monitor_list);
-    /* Destroy the Monitor lock to use */
-    err = jvmti->DestroyRawMonitor(lock);
-    check_jvmti_error(jvmti, err, "destroy raw monitor");
     /* Print death message */
     stdout_message("VMDeath...\n");
 }
@@ -215,8 +205,16 @@
     /* We just cast the tag to a C++ pointer and delete it.
      *   we know it can only be a Monitor *.
      */
-    Monitor *m;
+    Monitor   *m;
     /*LINTED*/
     m = (Monitor *)(ptrdiff_t)tag;
+    if (monitor_count > 1) {
+        /* Move the last element to this Monitor's slot */
+        int slot = m->get_slot();
+        Monitor *last = monitor_list[monitor_count-1];
+        monitor_list[slot] = last;
+        last->set_slot(slot);
+    }
+    monitor_count--;
     delete m;
 }
--- a/src/share/demo/jvmti/waiters/Agent.hpp	Sat Sep 12 15:30:13 2009 -0700
+++ b/src/share/demo/jvmti/waiters/Agent.hpp	Mon Sep 14 15:29:13 2009 +0100
@@ -34,8 +34,12 @@
 class Agent {
 
   private:
-    jrawMonitorID lock;
+    enum {
+      initial_monitor_list_size = 64,
+      monitor_list_grow_size = 16
+    };
     Monitor     **monitor_list;
+    unsigned      monitor_list_size;
     unsigned      monitor_count;
     Thread *get_thread(jvmtiEnv *jvmti, JNIEnv *env, jthread thread);
     Monitor *get_monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object);
--- a/src/share/demo/jvmti/waiters/Monitor.cpp	Sat Sep 12 15:30:13 2009 -0700
+++ b/src/share/demo/jvmti/waiters/Monitor.cpp	Mon Sep 14 15:29:13 2009 +0100
@@ -73,6 +73,16 @@
         name, contends, waits, timeouts);
 }
 
+int Monitor::get_slot()
+{
+    return slot;
+}
+
+void Monitor::set_slot(int aslot)
+{
+    slot = aslot;
+}
+
 void Monitor::contended()
 {
     contends++;
--- a/src/share/demo/jvmti/waiters/Monitor.hpp	Sat Sep 12 15:30:13 2009 -0700
+++ b/src/share/demo/jvmti/waiters/Monitor.hpp	Mon Sep 14 15:29:13 2009 +0100
@@ -35,6 +35,7 @@
 
   private:
     char     name[64];
+    int      slot;
     unsigned contends;
     unsigned waits;
     unsigned timeouts;
@@ -42,6 +43,8 @@
   public:
     Monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object);
     ~Monitor();
+    int get_slot();
+    void set_slot(int i);
     void contended();
     void waited();
     void timeout();