169N/A/*
2362N/A * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/* @test
169N/A * @bug 4118600
0N/A * @summary RMI UnmarshallException, interaction on stopping a thread.
0N/A *
0N/A * @bug 4177704
0N/A * @summary RuntimeExceptions can corrupt call connections that may be reused.
0N/A *
0N/A * @author Laird Dornin
0N/A *
0N/A * @library ../../../testlibrary
5551N/A * @build TestLibrary CheckUnmarshal CheckUnmarshalOnStopThread_Stub
5551N/A * PoisonPill RuntimeExceptionParameter
169N/A * @run main/othervm/timeout=480 CheckUnmarshalOnStopThread
0N/A */
0N/A
0N/Aimport java.rmi.*;
0N/Aimport java.rmi.server.*;
0N/Aimport java.io.*;
0N/Aimport java.rmi.registry.*;
0N/A
0N/A/**
169N/A * Description for 4118600:
0N/A *
0N/A * If an rmi call thread is stopped while unmarshalling a return
0N/A * value), java.lang.ThreadDeath will be thrown during
0N/A * UnicastRef.invoke(...). If rmi handles the Error properly, the
0N/A * remote method connection will not be reused. Otherwise the
0N/A * connection can be freed and reused in a corrupted state, which will
0N/A * lead to the throwing of an UnmarshalException the next time the
0N/A * connection is used.
0N/A *
0N/A * To test RMI Error handling, the test invokes the remote call,
0N/A * getPoisonPill, a number of times. This method returns an object
0N/A * which throws an Error on return value deserialization (from its
0N/A * readObject method). If RMI handles the error correctly, another
0N/A * remote call, ping, should execute correctly (i.e. with no
0N/A * exceptions). The test fails if the ping method throws an
0N/A * UnmarshalException.
0N/A *
0N/A * The old way that the test used to operate:
0N/A *
0N/A * Iterate a large number of times: each iteration spawns a thread
0N/A * that makes multiple rmi calls, sleep for 10 milliseconds, then stop
0N/A * the thread that is making the rmi calls (hopefully during return
0N/A * value Unmarshalling).
0N/A *
0N/A * Count the number of UnmarshalExceptions that occur during test
0N/A * iterations. If this number is > 10, then the test fails.
0N/A *
0N/A * Note: Even if rmi is catching java.lang.ThreadDeath properly, other
0N/A * types of exceptions (often related to monitor state, etc.) can
0N/A * occur. This test is only written to track UnmarshalExceptions;
0N/A * success/failure does not depend on other types of problems.
0N/A *
169N/A * Description for 4177704:
169N/A *
0N/A * Similar situation as for 4177704 except that instead of just
0N/A * ensuring that RMI properly handles Errors, the second part of the
0N/A * test ensures that RMI deals with RuntimeExceptions correctly.
0N/A *
0N/A * Test also ensures that call connections are freed without reuse
0N/A * when RuntimeExceptions are thrown during the marshalling of call
0N/A * parameters. An object that throws a RuntimeException in its
0N/A * writeObject method helps to carry out this part of the test.
0N/A */
169N/Apublic class CheckUnmarshalOnStopThread
169N/A extends UnicastRemoteObject
169N/A implements CheckUnmarshal
0N/A{
0N/A final static int RUNTIME_PILL = 1;
0N/A public static int typeToThrow = 0;
0N/A
0N/A /*
169N/A * remote object implementation
0N/A */
0N/A
0N/A CheckUnmarshalOnStopThread() throws RemoteException { }
0N/A
0N/A public PoisonPill getPoisonPill() throws RemoteException {
169N/A return new PoisonPill(new Integer(0));
0N/A }
0N/A
0N/A public Object ping() throws RemoteException {
169N/A return (Object) new Integer(0);
0N/A }
0N/A
0N/A public void passRuntimeExceptionParameter(
169N/A RuntimeExceptionParameter rep) throws RemoteException
0N/A {
169N/A // will never be called
0N/A }
0N/A
0N/A public static void main(String [] args) {
0N/A
169N/A Object dummy = new Object();
169N/A CheckUnmarshal cu = null;
169N/A CheckUnmarshalOnStopThread cuonst = null;
0N/A
169N/A System.err.println("\nregression test for bugs: " +
169N/A "4118600 and 4177704\n");
0N/A
169N/A try {
169N/A cuonst = new CheckUnmarshalOnStopThread();
169N/A cu = (CheckUnmarshal) UnicastRemoteObject.toStub(cuonst);
0N/A
169N/A // make sure that RMI will free connections appropriately
169N/A // under several situations:
0N/A
169N/A // when Errors are thrown during parameter unmarshalling
169N/A System.err.println("testing to see if RMI will handle errors");
169N/A ensureConnectionsAreFreed(cu, true);
0N/A
169N/A // when RuntimeExceptions are thrown during parameter unmarshalling
169N/A System.err.println("testing to see if RMI will handle " +
169N/A "runtime exceptions");
169N/A typeToThrow = RUNTIME_PILL;
169N/A ensureConnectionsAreFreed(cu, true);
0N/A
169N/A // when RuntimeExceptions are thrown during parameter marshalling
169N/A System.err.println("testing to see if RMI will handle " +
169N/A "runtime exceptions thrown during " +
169N/A "parameter marshalling");
169N/A ensureConnectionsAreFreed(cu, false);
0N/A
169N/A System.err.println
169N/A ("\nsuccess: CheckUnmarshalOnStopThread test passed ");
0N/A
169N/A } catch (Exception e) {
169N/A TestLibrary.bomb(e);
169N/A } finally {
169N/A cu = null;
169N/A deactivate(cuonst);
169N/A }
0N/A }
169N/A
169N/A static void ensureConnectionsAreFreed(CheckUnmarshal cu, boolean getPill)
169N/A throws Exception
0N/A {
169N/A // invoke a remote call that will corrupt a call connection
169N/A // that will not be freed (if the bug is not fixed)
0N/A
169N/A for (int i = 0 ; i < 250 ; i++) {
169N/A try {
169N/A Object test = cu.ping();
169N/A if (getPill) {
169N/A cu.getPoisonPill();
169N/A } else {
169N/A cu.passRuntimeExceptionParameter(
169N/A new RuntimeExceptionParameter());
169N/A }
169N/A } catch (Error e) {
169N/A // expect an Error from call unmarshalling, ignore it
169N/A } catch (RuntimeException e) {
169N/A // " RuntimeException "
169N/A }
169N/A }
0N/A
169N/A System.err.println("remote calls passed, received no " +
169N/A "unmarshal exceptions\n\n");
0N/A }
0N/A
0N/A static void deactivate(RemoteServer r) {
169N/A // make sure that the object goes away
169N/A try {
169N/A System.err.println("deactivating object.");
169N/A UnicastRemoteObject.unexportObject(r, true);
169N/A } catch (Exception e) {
169N/A e.getMessage();
169N/A e.printStackTrace();
169N/A }
0N/A }
0N/A}