1 /* 2 * Copyright (c) 1998, 2016, 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 4094891 8157777 26 * @summary unable to retry call if cached connection to server is used 27 * @library ../../../../java/rmi/testlibrary 28 * @modules java.rmi/sun.rmi.registry 29 * java.rmi/sun.rmi.server 30 * java.rmi/sun.rmi.transport 31 * java.rmi/sun.rmi.transport.tcp 32 * @build TestLibrary REGISTRY RegistryRunner 33 * @run main/othervm DeadCachedConnection 34 */ 35 36 /* Fault: Cached connections used for remote invocations exhibited 37 * failure (sudden EOF or a TCP-related exception) immediately on 38 * sending a new request. It was then impossible to tell whether the 39 * connection had managed to transport the request before dying; even 40 * deserialization of request arguments is non-idempotent in general. 41 * 42 * In fact, this problem cannot be solved generally without rewriting 43 * the protocol. For now, the common case is the closing of an idle 44 * connection by a loaded/bored/dead server host. 45 * 46 * The fix is/was to trivially attempt to execute a non-blocking read 47 * on the connection before reusing it, to see if an exception/EOF is 48 * waiting for delivery. This is a 99%/1% solution, but until the 49 * great protocol rewrite, it's the best option. 50 * 51 * Reproducing is by establishing a connection to a registry and 52 * killing/restarting that registry (this forces the TCP connection 53 * to close). The next call to the registry will use the (stale) 54 * cached connection, and will fail without the bugfix. 55 */ 56 57 import java.io.*; 58 import java.rmi.*; 59 import java.rmi.registry.*; 60 import java.rmi.server.*; 61 62 public class DeadCachedConnection { 63 64 static public void main(String[] argv) 65 throws Exception { 66 try { 67 Registry reg = null; 68 int port = makeRegistry(0); 69 70 // Get a handle to the registry 71 System.err.println ("Locating just-started registry..."); 72 try { 73 reg = LocateRegistry.getRegistry(port); 74 } catch (RemoteException e) { 75 throw new InternalError ("Can't find registry after starting it."); 76 } 77 78 // Contact the registry by invoking something on it. 79 System.err.println ("Connecting to registry..."); 80 String[] junk = reg.list(); 81 82 // Kill and restart the registry 83 System.err.println("Killing registry..."); 84 killRegistry(); 85 System.err.println("Restarting registry..."); 86 makeRegistry(port); 87 88 // Try again (this is the test) 89 System.err.println("Trying to use registry in spite of stale cache..."); 90 junk = reg.list(); 91 92 System.err.println("Test succeeded."); 93 } catch (Exception e) { 94 TestLibrary.bomb(e); 95 } finally { 96 // dont leave the registry around to affect other tests. 97 killRegistry(); 98 } 99 } 100 101 public static int makeRegistry(int port) { 102 try { 103 subreg = REGISTRY.createREGISTRY(System.out, System.err, "", port); 104 subreg.start(); 105 int regPort = subreg.getPort(); 106 System.out.println("Starting registry on port " + regPort); 107 return regPort; 108 } catch (IOException e) { 109 // one of these is summarily dropped, can't remember which one 110 System.out.println ("Test setup failed - cannot run rmiregistry"); 111 TestLibrary.bomb("Test setup failed - cannot run test", e); 112 } 113 return -1; 114 } 115 116 private static REGISTRY subreg = null; 117 118 public static void killRegistry() throws InterruptedException { 119 if (subreg != null) { 120 subreg.shutdown(); 121 subreg = null; 122 } 123 } 124 }