J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright 1998-1999 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| 20 | * CA 95054 USA or visit www.sun.com if you need additional information or |
| 21 | * have any 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 | } |