8029360: java/rmi/transport/dgcDeadLock/DGCDeadLock.java failing intermittently
authormli
Tue, 20 Dec 2016 17:34:11 -0800
changeset 42918 038d77430a46
parent 42845 17469f16fbb4
child 42919 10689de32ce6
8029360: java/rmi/transport/dgcDeadLock/DGCDeadLock.java failing intermittently Reviewed-by: dfuchs
jdk/test/ProblemList.txt
jdk/test/java/rmi/testlibrary/REGISTRY.java
jdk/test/java/rmi/testlibrary/RegistryRunner.java
jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java
jdk/test/java/rmi/transport/dgcDeadLock/TestImpl.java
--- a/jdk/test/ProblemList.txt	Wed Jul 05 22:37:14 2017 +0200
+++ b/jdk/test/ProblemList.txt	Tue Dec 20 17:34:11 2016 -0800
@@ -203,8 +203,6 @@
 
 sun/rmi/rmic/newrmic/equivalence/run.sh                         8145980 generic-all
 
-java/rmi/transport/dgcDeadLock/DGCDeadLock.java                 8029360 macosx-all
-
 java/rmi/registry/readTest/readTest.sh                          7146543 generic-all
 
 ############################################################################
--- a/jdk/test/java/rmi/testlibrary/REGISTRY.java	Wed Jul 05 22:37:14 2017 +0200
+++ b/jdk/test/java/rmi/testlibrary/REGISTRY.java	Tue Dec 20 17:34:11 2016 -0800
@@ -33,28 +33,48 @@
  */
 public class REGISTRY extends JavaVM {
 
-    private static double startTimeout = 20_000 * TestLibrary.getTimeoutFactor();
+    private static final double START_TIMEOUT =
+            20_000 * TestLibrary.getTimeoutFactor();
+    private static final String DEFAULT_RUNNER = "RegistryRunner";
 
     private int port = -1;
 
-    private REGISTRY(OutputStream out, OutputStream err,
+    private REGISTRY(String runner, OutputStream out, OutputStream err,
                     String options, int port) {
-        super("RegistryRunner", options, Integer.toString(port), out, err);
+        super(runner, options, Integer.toString(port), out, err);
+        try {
+            Class runnerClass = Class.forName(runner);
+            if (!RegistryRunner.class.isAssignableFrom(runnerClass)) {
+                throw new RuntimeException("runner class must be RegistryRunner"
+                        + " or its sub class");
+            }
+        } catch (ClassNotFoundException ex) {
+            throw new RuntimeException(ex);
+        }
         this.port = port;
     }
 
     public static REGISTRY createREGISTRY() {
-        return createREGISTRY(System.out, System.err, "", 0);
+        return createREGISTRYWithRunner(DEFAULT_RUNNER, System.out, System.err, "", 0);
     }
 
     public static REGISTRY createREGISTRY(OutputStream out, OutputStream err,
                                     String options, int port) {
+        return createREGISTRYWithRunner(DEFAULT_RUNNER, out, err, options, port);
+    }
+
+    public static REGISTRY createREGISTRYWithRunner(String runner, String options) {
+        return createREGISTRYWithRunner(runner, System.out, System.err, options, 0);
+    }
+
+    public static REGISTRY createREGISTRYWithRunner(String runner, OutputStream out,
+                                        OutputStream err, String options, int port) {
         options += " --add-exports=java.rmi/sun.rmi.registry=ALL-UNNAMED"
-                 + " --add-exports=java.rmi/sun.rmi.server=ALL-UNNAMED"
-                 + " --add-exports=java.rmi/sun.rmi.transport=ALL-UNNAMED"
-                 + " --add-exports=java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED";
-        REGISTRY reg = new REGISTRY(out, err, options, port);
-        return reg;
+                + " --add-exports=java.rmi/sun.rmi.server=ALL-UNNAMED"
+                + " --add-exports=java.rmi/sun.rmi.transport=ALL-UNNAMED"
+                + " --add-exports=java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED";
+       REGISTRY reg = new REGISTRY(runner, out, err, options, port);
+       return reg;
     }
 
     /**
@@ -65,7 +85,7 @@
     public void start() throws IOException {
         super.start();
         long startTime = System.currentTimeMillis();
-        long deadline = TestLibrary.computeDeadline(startTime, (long)startTimeout);
+        long deadline = TestLibrary.computeDeadline(startTime, (long)START_TIMEOUT);
         while (true) {
             try {
                 Thread.sleep(1000);
--- a/jdk/test/java/rmi/testlibrary/RegistryRunner.java	Wed Jul 05 22:37:14 2017 +0200
+++ b/jdk/test/java/rmi/testlibrary/RegistryRunner.java	Tue Dec 20 17:34:11 2016 -0800
@@ -95,17 +95,17 @@
         return port;
     }
 
-    public static void main(String[] args) {
-
+    /**
+     * port 0 means to use ephemeral port to start registry.
+     */
+    protected static int init(String[] args) {
         try {
             if (args.length == 0) {
                 System.err.println("Usage: <port>");
                 System.exit(0);
             }
             int port = -1;
-            try {
-                port = Integer.parseInt(args[0]);
-            } catch (NumberFormatException ignore) { }
+            port = Integer.parseInt(args[0]);
 
             // create a registry
             registry = LocateRegistry.createRegistry(port);
@@ -118,14 +118,30 @@
             Naming.rebind("rmi://localhost:" + port +
                           "/RemoteExiter", exiter);
 
-            // this output is important for REGISTRY to get the port
-            // where rmiregistry is serving
-            System.out.println(PORT_LABEL_START + port + PORT_LABEL_END);
-
+            return port;
         } catch (Exception e) {
             System.err.println(e.getMessage());
             e.printStackTrace();
             System.exit(-1);
         }
+        return -1;
+    }
+
+    /**
+     * REGISTRY.start() will filter the output of registry subprocess,
+     * when valid port is detected, REGISTRY.start() returns.
+     * So, for subclass, it's important to call this method after registry
+     * is initialized and necessary remote objects have been bound.
+     */
+    protected static void notify(int port) {
+        // this output is important for REGISTRY to get the port
+        // where rmiregistry is serving
+        System.out.println(PORT_LABEL_START + port + PORT_LABEL_END);
+        System.out.flush();
+    }
+
+    public static void main(String[] args) {
+        int port = init(args);
+        notify(port);
     }
 }
--- a/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java	Wed Jul 05 22:37:14 2017 +0200
+++ b/jdk/test/java/rmi/transport/dgcDeadLock/DGCDeadLock.java	Tue Dec 20 17:34:11 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,7 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary Test TestImpl TestImpl_Stub
+ * @build TestLibrary Test TestImpl REGISTRY RegistryRunner
  * @run main/othervm/policy=security.policy/timeout=360 DGCDeadLock
  */
 
@@ -55,11 +55,12 @@
 import java.io.*;
 
 public class DGCDeadLock implements Runnable {
-    private static final int REGISTRY_PORT = TestLibrary.getUnusedRandomPort();
     final static public int HOLD_TARGET_TIME = 25000;
-    public static int TEST_FAIL_TIME = HOLD_TARGET_TIME + 30000;
-    public static boolean finished = false;
-    static DGCDeadLock test = new DGCDeadLock();
+    public static final double TEST_FAIL_TIME =
+            (HOLD_TARGET_TIME + 30000) * TestLibrary.getTimeoutFactor();
+    public static volatile boolean finished = false;
+    static final DGCDeadLock test = new DGCDeadLock();
+    static volatile int registryPort = -1;
 
     static {
         System.setProperty("sun.rmi.transport.cleanInterval", "50");
@@ -67,7 +68,7 @@
 
     static public void main(String[] args) {
 
-        JavaVM testImplVM = null;
+        REGISTRY testImplVM = null;
 
         System.err.println("\nregression test for 4118056\n");
         TestLibrary.suggestSecurityManager("java.rmi.RMISecurityManager");
@@ -75,18 +76,15 @@
         try {
             String options = " -Djava.security.policy=" +
                 TestParams.defaultPolicy +
-                " --add-exports java.rmi/sun.rmi.registry=ALL-UNNAMED" +
-                " --add-exports java.rmi/sun.rmi.server=ALL-UNNAMED" +
                 " --add-opens java.rmi/sun.rmi.transport=ALL-UNNAMED" +
-                " --add-exports java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" +
                 " -Djava.rmi.dgc.leaseValue=500000" +
-                "  -Dsun.rmi.dgc.checkInterval=" +
+                " -Dsun.rmi.dgc.checkInterval=" +
                 (HOLD_TARGET_TIME - 5000) +
-                "   -Drmi.registry.port=" + REGISTRY_PORT +
                 "" ;
 
-            testImplVM = new JavaVM("TestImpl", options, "");
+            testImplVM = REGISTRY.createREGISTRYWithRunner("TestImpl", options);
             testImplVM.start();
+            registryPort = testImplVM.getPort();
 
             synchronized (test) {
                 Thread t = new Thread(test);
@@ -94,7 +92,7 @@
                 t.start();
 
                 // wait for the remote calls to take place
-                test.wait(TEST_FAIL_TIME);
+                test.wait((long)TEST_FAIL_TIME);
             }
 
             if (!finished) {
@@ -106,8 +104,12 @@
                                "finished in time.");
 
         } catch (Exception e) {
-            testImplVM = null;
-            TestLibrary.bomb("test failed", e);
+            TestLibrary.bomb("test failed in main()", e);
+        } finally {
+            if (testImplVM != null) {
+                testImplVM.shutdown();
+                testImplVM = null;
+            }
         }
     }
 
@@ -115,12 +117,9 @@
         try {
             String echo = null;
 
-            // give the test remote object time to initialize.
-            Thread.currentThread().sleep(8000);
-
             // create a test client
             Test foo = (Test) Naming.lookup("rmi://:" +
-                                            REGISTRY_PORT +
+                                            registryPort +
                                             "/Foo");
             echo = foo.echo("Hello world");
             System.err.println("Test object created.");
@@ -139,7 +138,7 @@
 
             //import "Bar"
             Test bar = (Test) Naming.lookup("rmi://:" +
-                                            REGISTRY_PORT +
+                                            registryPort +
                                             "/Bar");
 
             /* infinite loop to show the liveness of Client,
@@ -155,11 +154,16 @@
                 finished = true;
 
             } catch (RemoteException e) {
+                System.err.println("catch RemoteException");
+                e.printStackTrace();
             }
 
         } catch (Exception e) {
-            TestLibrary.bomb("test failed", e);
+            TestLibrary.bomb("test failed in run()", e);
         } finally {
+            synchronized(this) {
+                notify();
+            }
         }
     }
 }
--- a/jdk/test/java/rmi/transport/dgcDeadLock/TestImpl.java	Wed Jul 05 22:37:14 2017 +0200
+++ b/jdk/test/java/rmi/transport/dgcDeadLock/TestImpl.java	Tue Dec 20 17:34:11 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
 import java.rmi.registry.*;
 import java.rmi.server.*;
 
-public class TestImpl extends UnicastRemoteObject
+public class TestImpl extends RegistryRunner
     implements Test {
     static Thread locker = null;
     static TestImpl foo = null;
@@ -53,12 +53,8 @@
     }
 
     static public void main(String[] args) {
-        Registry registry = null;
-
         try {
-            int registryPort = Integer.parseInt(System.getProperty("rmi.registry.port"));
-            registry = java.rmi.registry.LocateRegistry.
-                createRegistry(registryPort);
+            int registryPort = RegistryRunner.init(args);
 
             //export "Foo"
             foo = new TestImpl();
@@ -75,16 +71,11 @@
             } catch (Exception e) {
                 throw new RemoteException(e.getMessage());
             }
-            Thread.sleep(DGCDeadLock.TEST_FAIL_TIME);
-            System.err.println("object vm exiting...");
-            System.exit(0);
 
+            RegistryRunner.notify(registryPort);
         } catch (Exception e) {
             System.err.println(e.getMessage());
             e.printStackTrace();
-        } finally {
-            TestLibrary.unexport(registry);
-            registry = null;
         }
     }