[jboss-svn-commits] JBL Code SVN: r29464 - in labs/jbosstm/workspace/adinn/byteman/trunk: src/org/jboss/byteman/synchronization and 4 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Fri Sep 25 06:25:45 EDT 2009


Author: adinn
Date: 2009-09-25 06:25:45 -0400 (Fri, 25 Sep 2009)
New Revision: 29464

Added:
   labs/jbosstm/workspace/adinn/byteman/trunk/tests/dd/scripts/bugfixes/TestWaitAfterSignalWakeMustMeet.txt
   labs/jbosstm/workspace/adinn/byteman/trunk/tests/src/org/jboss/byteman/tests/bugfixes/TestWaitAfterSignalWakeMustMeet.java
   labs/jbosstm/workspace/adinn/byteman/trunk/tests/src/org/jboss/byteman/tests/helpers/TestWaitAfterSignalWakeMustMeetHelper.java
Modified:
   labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/helper/Helper.java
   labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/synchronization/Waiter.java
   labs/jbosstm/workspace/adinn/byteman/trunk/tests/build.xml
Log:
fixed bug in waiter code and added test for it

Modified: labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/helper/Helper.java
===================================================================
--- labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/helper/Helper.java	2009-09-25 10:19:11 UTC (rev 29463)
+++ labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/helper/Helper.java	2009-09-25 10:25:45 UTC (rev 29464)
@@ -433,9 +433,12 @@
                         // do nothing
                     }
                 }
-                // remove the association between the waiter and the wait map
-                removeWaiter(waiter);
             }
+
+            // remove the association between the waiter and the wait map
+            synchronized (waitMap) {
+                removeWaiter(identifier);
+            }
             return true;
         }
     }
@@ -515,9 +518,11 @@
                         // do nothing
                     }
                 }
-                // remove the association between the waiter and the wait map
-                removeWaiter(waiter);
             }
+            // remove the association between the waiter and the wait map
+            synchronized (waitMap) {
+                removeWaiter(identifier);
+            }
             return true;
         }
     }

Modified: labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/synchronization/Waiter.java
===================================================================
--- labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/synchronization/Waiter.java	2009-09-25 10:19:11 UTC (rev 29463)
+++ labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/synchronization/Waiter.java	2009-09-25 10:25:45 UTC (rev 29464)
@@ -63,7 +63,7 @@
         // if a signalKill was used then we have to throw an exception otherwise we just return
         
         if (killed) {
-            throw new ExecuteException("Waiter.waitFor waiting thread killed for " + waiterFor);
+            throw new ExecuteException("Waiter.waitFor : killed thread waiting for " + waiterFor);
         }
     }
 
@@ -126,4 +126,12 @@
      */
 
     private boolean waiting;
+
+    /**
+     * getter for signalled flag
+     * @return signalled
+     */
+    public boolean isSignalled() {
+        return signalled;
+    }
 }

Modified: labs/jbosstm/workspace/adinn/byteman/trunk/tests/build.xml
===================================================================
--- labs/jbosstm/workspace/adinn/byteman/trunk/tests/build.xml	2009-09-25 10:19:11 UTC (rev 29463)
+++ labs/jbosstm/workspace/adinn/byteman/trunk/tests/build.xml	2009-09-25 10:25:45 UTC (rev 29464)
@@ -322,6 +322,16 @@
                 <pathelement location="${junit.home}/${junit.jar}"/>
             </classpath>
             <jvmarg value="-javaagent:${byteman.home}/${byteman.jar}=script:${scripts.dir}/javaops/TestArithmetic.txt"/>
+            <!-- uncomment to dump generated code
+            <jvmarg value="-Dorg.jboss.byteman.dump.generated.classes"/>
+            <jvmarg value="-Dorg.jboss.byteman.dump.generated.classes.directory=dump"/>
+            -->
+            <!-- uncomment to enable debug
+            <jvmarg value="-Xdebug"/>
+            <jvmarg  value="-Xnoagent"/>
+            <jvmarg  value="-Djava.compiler=NONE"/>
+            <jvmarg  value="-Xrunjdwp:transport=dt_socket,server=n,suspend=y,address=5005"/>
+            -->
             <jvmarg value="-Dorg.jboss.byteman.compileToBytecode"/>
             <test name="org.jboss.byteman.tests.javaops.TestArithmetic"/>
         </junit>
@@ -404,8 +414,8 @@
             <jvmarg  value="-Xnoagent"/>
             <jvmarg  value="-Djava.compiler=NONE"/>
             <jvmarg  value="-Xrunjdwp:transport=dt_socket,server=n,suspend=y,address=5005"/>
+            -->
             <test name="org.jboss.byteman.tests.javaops.TestArray"/>
-            -->
         </junit>
     </target>
 
@@ -494,6 +504,27 @@
           -->
           <test name="org.jboss.byteman.tests.bugfixes.TestThrowAction"/>
         </junit>
+        <junit fork="true" showoutput="true">
+          <classpath>
+              <pathelement location="${build.lib.dir}/byteman-tests.jar"/>
+              <pathelement location="${junit.home}/${junit.jar}"/>
+          </classpath>
+          <jvmarg value="-javaagent:${byteman.home}/${byteman.jar}=script:${scripts.dir}/bugfixes/TestWaitAfterSignalWakeMustMeet.txt"/>
+          <!-- uncomment for verbose byteman output
+          <jvmarg value="-Dorg.jboss.byteman.verbose"/>
+          -->
+          <!-- uncomment to dump generated code
+          <jvmarg value="-Dorg.jboss.byteman.dump.generated.classes"/>
+          <jvmarg value="-Dorg.jboss.byteman.dump.generated.classes.directory=dump"/>
+          -->
+          <!-- uncomment to enable debug
+          <jvmarg value="-Xdebug"/>
+          <jvmarg  value="-Xnoagent"/>
+          <jvmarg  value="-Djava.compiler=NONE"/>
+          <jvmarg  value="-Xrunjdwp:transport=dt_socket,server=n,suspend=y,address=5005"/>
+          -->
+          <test name="org.jboss.byteman.tests.bugfixes.TestWaitAfterSignalWakeMustMeet"/>
+        </junit>
   </target>
 
     <target name="tests.bugfixes.compiled">
@@ -588,6 +619,28 @@
           -->
           <test name="org.jboss.byteman.tests.bugfixes.TestThrowAction"/>
       </junit>
+      <junit fork="true" showoutput="true">
+          <classpath>
+              <pathelement location="${build.lib.dir}/byteman-tests.jar"/>
+              <pathelement location="${junit.home}/${junit.jar}"/>
+          </classpath>
+          <jvmarg value="-javaagent:${byteman.home}/${byteman.jar}=script:${scripts.dir}/bugfixes/TestWaitAfterSignalWakeMustMeet.txt"/>
+          <jvmarg value="-Dorg.jboss.byteman.compileToBytecode"/>
+          <!-- uncomment for verbose byteman output
+          <jvmarg value="-Dorg.jboss.byteman.verbose"/>
+          -->
+          <!-- uncomment to dump generated code
+          <jvmarg value="-Dorg.jboss.byteman.dump.generated.classes"/>
+          <jvmarg value="-Dorg.jboss.byteman.dump.generated.classes.directory=dump"/>
+          -->
+          <!-- uncomment to enable debug
+          <jvmarg value="-Xdebug"/>
+          <jvmarg  value="-Xnoagent"/>
+          <jvmarg  value="-Djava.compiler=NONE"/>
+          <jvmarg  value="-Xrunjdwp:transport=dt_socket,server=n,suspend=y,address=5005"/>
+          -->
+          <test name="org.jboss.byteman.tests.bugfixes.TestWaitAfterSignalWakeMustMeet"/>
+      </junit>
   </target>
 
 

Added: labs/jbosstm/workspace/adinn/byteman/trunk/tests/dd/scripts/bugfixes/TestWaitAfterSignalWakeMustMeet.txt
===================================================================
--- labs/jbosstm/workspace/adinn/byteman/trunk/tests/dd/scripts/bugfixes/TestWaitAfterSignalWakeMustMeet.txt	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/byteman/trunk/tests/dd/scripts/bugfixes/TestWaitAfterSignalWakeMustMeet.txt	2009-09-25 10:25:45 UTC (rev 29464)
@@ -0,0 +1,123 @@
+##############################################################################
+# JBoss, Home of Professional Open Source
+# Copyright 2009, Red Hat Middleware LLC, and individual contributors
+# by the @authors tag. See the copyright.txt in the distribution for a
+# full listing of individual contributors.
+#
+# This is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# This software is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this software; if not, write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+#
+# @authors Andrew Dinn
+#
+# Test for BYTEMAN-38
+
+##############################################################################
+# when test is entered we need to set up a rendezvous
+
+RULE setup
+CLASS TestWaitAfterSignalWakeMustMeet
+METHOD test
+HELPER org.jboss.byteman.tests.helpers.TestWaitAfterSignalWakeMustMeetHelper
+IF TRUE
+DO createRendezvous("test", 2, true)
+ENDRULE
+
+
+##############################################################################
+# when ensureSignalWake is called we need to ensure that another thread has
+# called signalWake. our helper specialises signalWake to allow this to be
+# checked
+
+RULE ensureSignalWait
+CLASS TestWaitAfterSignalWakeMustMeet
+METHOD ensureSignalWake
+HELPER org.jboss.byteman.tests.helpers.TestWaitAfterSignalWakeMustMeetHelper
+IF TRUE
+DO ensureSignalWake()
+ENDRULE
+
+##############################################################################
+# when ensureWaitFor is called we need to ensure that another thread has
+# called waitFor. our helper specialises waitFor to allow this to be
+# checked
+
+RULE ensureWaitFor
+CLASS TestWaitAfterSignalWakeMustMeet
+METHOD ensureWaitFor
+HELPER org.jboss.byteman.tests.helpers.TestWaitAfterSignalWakeMustMeetHelper
+IF TRUE
+DO ensureWaitFor()
+ENDRULE
+
+##############################################################################
+# when triggerWaitFor is called we need to do a waitFor
+
+RULE triggerWaitFor
+CLASS TestWaitAfterSignalWakeMustMeet
+METHOD triggerWaitFor
+HELPER org.jboss.byteman.tests.helpers.TestWaitAfterSignalWakeMustMeetHelper
+BIND test : TestEmptySignature = $0
+IF TRUE
+DO test.log("waitFor"),
+   waitFor("test")
+ENDRULE
+
+##############################################################################
+# when triggerSignalWake is called we need to do a signalWake
+
+RULE triggerSignalWake
+CLASS TestWaitAfterSignalWakeMustMeet
+METHOD triggerSignalWake
+HELPER org.jboss.byteman.tests.helpers.TestWaitAfterSignalWakeMustMeetHelper
+BIND test : TestEmptySignature = $0
+IF TRUE
+DO test.log("signalWake"),
+   signalWake("test", true)
+ENDRULE
+
+##############################################################################
+# when triggerRendezvous is called we need to do a rendezvous
+
+RULE triggerRendezvous
+CLASS TestWaitAfterSignalWakeMustMeet
+METHOD triggerRendezvous
+HELPER org.jboss.byteman.tests.helpers.TestWaitAfterSignalWakeMustMeetHelper
+IF TRUE
+DO rendezvous("test")
+ENDRULE
+
+##############################################################################
+# when triggerTimeoutCheck is called we need to wait and, if we timeout
+# throw an Exception
+
+RULE triggerTimeoutCheck
+CLASS TestWaitAfterSignalWakeMustMeet
+METHOD triggerTimeoutCheck
+IF TRUE
+DO waitFor("timeout", 60 * 1000),
+   throw Exception("failed with timeout")
+ENDRULE
+
+##############################################################################
+# when triggerTimeoutCancel is called we need to call signalThrow to cause
+# a runtime exception in the main thread.
+
+RULE triggerTimeoutCancel
+CLASS TestWaitAfterSignalWakeMustMeet
+METHOD triggerTimeoutCancel
+IF TRUE
+DO signalThrow("timeout")
+ENDRULE
+

Added: labs/jbosstm/workspace/adinn/byteman/trunk/tests/src/org/jboss/byteman/tests/bugfixes/TestWaitAfterSignalWakeMustMeet.java
===================================================================
--- labs/jbosstm/workspace/adinn/byteman/trunk/tests/src/org/jboss/byteman/tests/bugfixes/TestWaitAfterSignalWakeMustMeet.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/byteman/trunk/tests/src/org/jboss/byteman/tests/bugfixes/TestWaitAfterSignalWakeMustMeet.java	2009-09-25 10:25:45 UTC (rev 29464)
@@ -0,0 +1,121 @@
+package org.jboss.byteman.tests.bugfixes;
+
+import org.jboss.byteman.tests.Test;
+import org.jboss.byteman.rule.exception.ExecuteException;
+
+/**
+ * This test accompaniesBYTEMAN-38. The bug happens when the same key is used for two successive pairs of
+ * calls to builtin helper methods waitFor(key) and signalWake(key, true). When the first call to waitFor
+ * happens before the first call to signalWake then the cleanup under signalWake fails to remove the
+ * Waiter object associated with key. The next call to waitFor finds a waiter which has been signalled
+ * and returns immediately. The call to signalWake shoudl remove the waiter before returning.
+ */
+public class TestWaitAfterSignalWakeMustMeet extends Test
+{
+    public TestWaitAfterSignalWakeMustMeet() {
+        super(TestWaitAfterSignalWakeMustMeet.class.getCanonicalName());
+    }
+
+    public void test() throws Exception
+    {
+        Thread thread1 = new Thread() {
+            public void run()
+            {
+                runThread1();
+            }
+        };
+        Thread thread2 = new Thread() {
+            public void run()
+            {
+                runThread2();
+            }
+        };
+        thread1.start();
+        thread2.start();
+        try {
+            triggerTimeoutCheck();
+        } catch (ExecuteException e) {
+            log("caught execute exception");
+        } catch (Exception e) {
+            fail(e.getMessage());
+        }
+        checkOutput();
+    }
+
+    public void ensureSignalWake()
+    {
+        // do nothing. this is just for the purpose of triggering
+    }
+
+    public void ensureWaitFor()
+    {
+        // do nothing. this is just for the purpose of triggering
+    }
+
+    public void triggerWaitFor()
+    {
+        // do nothing. this is just for the purpose of triggering
+    }
+
+    public void triggerRendezvous()
+    {
+        // do nothing. this is just for the purpose of triggering
+    }
+
+    public void triggerSignalWake()
+    {
+        // do nothing. this is just for the purpose of triggering
+    }
+
+    public void triggerTimeoutCheck() throws Exception
+    {
+        // do nothing. this is just for the purpose of triggering
+    }
+
+    public void triggerTimeoutCancel()
+    {
+        // do nothing. this is just for the purpose of triggering
+    }
+
+    public void runThread1()
+    {
+        ensureSignalWake();
+        //System.out.println("thread1 : ensured signalWake sent");
+        triggerWaitFor();
+        //System.out.println("thread1 : triggered waitFor");
+        triggerRendezvous();
+        //System.out.println("thread1 : triggered rendezvous 1");
+        triggerWaitFor();
+        //System.out.println("thread1 : triggered waitFor");
+        triggerRendezvous();
+        //System.out.println("thread1 : triggered rendezvous 2");
+    }
+
+    public void runThread2()
+    {
+        triggerSignalWake();
+        //System.out.println("thread2 : triggered signalWake");
+        ensureWaitFor();
+        //System.out.println("thread2 : ensured waitFor");
+        triggerRendezvous();
+        //System.out.println("thread2 : triggered rendezvous 1");
+        ensureWaitFor();
+        //System.out.println("thread2 : ensured waitFor");
+        triggerSignalWake();
+        //System.out.println("thread2 : triggered signalWake");
+        triggerRendezvous();
+        //System.out.println("thread2 : triggered rendezvous 2");
+        triggerTimeoutCancel();
+        //System.out.println("thread2 : cancelled timeout");
+    }
+
+    @Override
+    public String getExpected() {
+        logExpected("signalWake");
+        logExpected("waitFor");
+        logExpected("waitFor");
+        logExpected("signalWake");
+        logExpected("caught execute exception");
+        return super.getExpected();
+    }
+}

Added: labs/jbosstm/workspace/adinn/byteman/trunk/tests/src/org/jboss/byteman/tests/helpers/TestWaitAfterSignalWakeMustMeetHelper.java
===================================================================
--- labs/jbosstm/workspace/adinn/byteman/trunk/tests/src/org/jboss/byteman/tests/helpers/TestWaitAfterSignalWakeMustMeetHelper.java	                        (rev 0)
+++ labs/jbosstm/workspace/adinn/byteman/trunk/tests/src/org/jboss/byteman/tests/helpers/TestWaitAfterSignalWakeMustMeetHelper.java	2009-09-25 10:25:45 UTC (rev 29464)
@@ -0,0 +1,87 @@
+package org.jboss.byteman.tests.helpers;
+
+import org.jboss.byteman.rule.helper.Helper;
+import org.jboss.byteman.rule.Rule;
+
+/**
+ */
+public class TestWaitAfterSignalWakeMustMeetHelper extends Helper
+{
+    protected TestWaitAfterSignalWakeMustMeetHelper(Rule rule) {
+        super(rule);
+    }
+
+    static boolean waitForCalled = false;
+    static boolean signalWakeCalled = false;
+    static Object lock = new Object();
+
+    public void waitFor(Object identifier, long timeout)
+    {
+        setWaitFor(); // there is a window here! we use a delay to close it
+        super.waitFor(identifier, timeout);
+    }
+
+    public boolean signalWake(Object identifier, boolean mustMeet)
+    {
+        setSignalWake(); // there is a window here! we use a delay to close it
+        return super.signalWake(identifier, mustMeet);
+    }
+
+    private void setWaitFor()
+    {
+        synchronized (lock) {
+            waitForCalled = true;
+            //System.out.println("waitForCalled <= true");
+            lock.notify();
+        }
+    }
+    
+    private void setSignalWake()
+    {
+        synchronized (lock) {
+            signalWakeCalled = true;
+            //System.out.println("signalWakeCalled <= true");
+            lock.notify();
+        }
+    }
+
+    public void ensureWaitFor()
+    {
+        synchronized (lock) {
+            //System.out.println("*waitForCalled = " + waitForCalled);
+            while (!waitForCalled) {
+                try {
+                    lock.wait();
+                } catch (InterruptedException e) {
+                    // do nothing
+                }
+                //System.out.println("**waitForCalled = " + waitForCalled);
+            }
+            //System.out.println("***waitForCalled = " + waitForCalled);
+            waitForCalled = false;
+            //System.out.println("****waitForCalled = " + waitForCalled);
+        }
+        // close the window -- maybe leaves a little air gap
+        delay(1000);
+    }
+
+    public void ensureSignalWake()
+    {
+        synchronized (lock) {
+            //System.out.println("*signalWakeCalled = " + signalWakeCalled);
+            while (!signalWakeCalled) {
+                try {
+                    lock.wait();
+                } catch (InterruptedException e) {
+                    // do nothing
+                }
+                //System.out.println("**signalWakeCalled = " + signalWakeCalled);
+            }
+            //System.out.println("***signalWakeCalled = " + signalWakeCalled);
+            signalWakeCalled = false;
+            //System.out.println("****signalWakeCalled = " + signalWakeCalled);
+        }
+        // close the window -- maybe leaves a little air gap
+        delay(1000);
+    }
+}



More information about the jboss-svn-commits mailing list