1 /*
   2  * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /* @test
  25  * @bug 4118056
  26  *
  27  * @summary synopsis: Distributed Garbage Collection Deadlock
  28  * @author Laird Dornin
  29  *
  30  * @library ../../testlibrary
  31  * @build DGCDeadLock
  32  * @build Test
  33  * @build TestImpl
  34  * @build TestImpl_Stub
  35  * @run main/othervm/policy=security.policy/timeout=360 DGCDeadLock
  36  */
  37 
  38 /* This test attempts to cause a deadlock between the rmi leaseChecker
  39  * thread and a thread that is servicing a dgc clean call. Before the
  40  * fix for this bug was implemented, deadlock could occur when the
  41  * leaseChecker held the lock on the lease table and the clean thread
  42  * held the lock on a target x. The clean thread would attempt to get
  43  * the lock on the leaseTable to do DGCImpl.unregisterTarget and the
  44  * leaseChecker would attempt to get the lock on x to do
  45  * Target.vmidDead.  Each thread held a resource that the other thread
  46  * was attempting to lock.
  47  *
  48  * This test causes the above conditions to occur and waits to see if
  49  * a given set of remote calls finishes "quickly enough."
  50  */
  51 
  52 import java.rmi.*;
  53 import java.io.*;
  54 
  55 public class DGCDeadLock implements Runnable {
  56 
  57     final static public int HOLD_TARGET_TIME = 25000;
  58     public static int TEST_FAIL_TIME = HOLD_TARGET_TIME + 30000;
  59     public static boolean finished = false;
  60     static DGCDeadLock test = new DGCDeadLock();
  61 
  62     static {
  63         System.setProperty("sun.rmi.transport.cleanInterval", "50");
  64     }
  65 
  66     static public void main(String[] args) {
  67 
  68         JavaVM testImplVM = null;
  69 
  70         System.err.println("\nregression test for 4118056\n");
  71         TestLibrary.suggestSecurityManager("java.rmi.RMISecurityManager");
  72 
  73         try {
  74             String options = " -Djava.security.policy=" +
  75                 TestParams.defaultPolicy +
  76                 " -Djava.rmi.dgc.leaseValue=500000" +
  77                 "  -Dsun.rmi.dgc.checkInterval=" +
  78                 (HOLD_TARGET_TIME - 5000) + "";
  79 
  80             testImplVM = new JavaVM("TestImpl", options, "");
  81             testImplVM.start();
  82 
  83             synchronized (test) {
  84                 Thread t = new Thread(test);
  85                 t.setDaemon(true);
  86                 t.start();
  87 
  88                 // wait for the remote calls to take place
  89                 test.wait(TEST_FAIL_TIME);
  90             }
  91 
  92             if (!finished) {
  93                 TestLibrary.bomb("Test failed, had exception or exercise" +
  94                                            " routines took too long to " +
  95                                            "execute");
  96             }
  97             System.err.println("Test passed, exercises " +
  98                                "finished in time.");
  99 
 100         } catch (Exception e) {
 101             testImplVM = null;
 102             TestLibrary.bomb("test failed", e);
 103         }
 104     }
 105 
 106     public void run() {
 107         try {
 108             String echo = null;
 109 
 110             // give the test remote object time to initialize.
 111             Thread.currentThread().sleep(8000);
 112 
 113             // create a test client
 114             Test foo = (Test) Naming.lookup("rmi://:" +
 115                                             TestLibrary.REGISTRY_PORT +
 116                                             "/Foo");
 117             echo = foo.echo("Hello world");
 118             System.err.println("Test object created.");
 119 
 120             /* give TestImpl time to lock the target in the
 121              * object table and any dirtys finish.
 122              */
 123             Thread.currentThread().sleep(5000);
 124 
 125             //unreference "Foo"
 126             foo = null;
 127 
 128             //garbage collect and finalize foo
 129             Runtime.getRuntime().gc();
 130             Runtime.getRuntime().runFinalization();
 131 
 132             //import "Bar"
 133             Test bar = (Test) Naming.lookup("rmi://:" +
 134                                             TestLibrary.REGISTRY_PORT +
 135                                             "/Bar");
 136 
 137             /* infinite loop to show the liveness of Client,
 138              * if we have deadlock remote call will not return
 139              */
 140             try {
 141                 for (int i = 0; i < 500; i++) {
 142                     echo = bar.echo("Remote call" + i);
 143                     Thread.sleep(10);
 144                 }
 145 
 146                 // flag exercises finished
 147                 finished = true;
 148 
 149             } catch (RemoteException e) {
 150             }
 151 
 152         } catch (Exception e) {
 153             TestLibrary.bomb("test failed", e);
 154         } finally {
 155         }
 156     }
 157 }