0N/A/*
5740N/A * Copyright (c) 1999, 2013, 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
0N/A * @bug 4183169
0N/A * @summary Minor problem with the way ReliableLog handles IOExceptions.
0N/A *
0N/A * @author Laird Dornin; code borrowed from Ann Wollrath
0N/A *
0N/A * @library ../../../testlibrary
5551N/A * @build TestLibrary RMID
5551N/A * TestSecurityManager RegisteringActivatable ShutdownGracefully_Stub
0N/A * @run main/othervm/policy=security.policy/timeout=700 ShutdownGracefully
0N/A */
0N/A
0N/Aimport java.rmi.activation.*;
0N/Aimport java.rmi.*;
0N/Aimport java.util.Properties;
0N/A
0N/A/**
0N/A * The test creates an rmid with a special security manager. After
0N/A * rmid makes two registrations (which is greater than rmid's
0N/A * snapshotInterval) the security manager stops allowing rmid to write
0N/A * to update and snapshot log files in rmid's log directory. The Test
0N/A * registers an Activatable object twice with different group ids.
0N/A * The second registration will cause rmid to have to write to a
0N/A * LogFile (it causes a snapshot) and the security manager will not
0N/A * allow the file write to happen. The test makes sure that rmid
0N/A * shuts down in a graceful manner without any explicit request to do
0N/A * so. The test will not exit for 400 seconds if rmid does not exit
0N/A * (after that time, the test will fail).
0N/A */
0N/Apublic class ShutdownGracefully
0N/A extends Activatable implements Runnable, RegisteringActivatable
0N/A{
0N/A private static RegisteringActivatable registering = null;
0N/A
0N/A private final static long SHUTDOWN_TIMEOUT = 400 * 1000;
0N/A
0N/A public static void main(String args[]) {
0N/A
0N/A RMID rmid = null;
0N/A
0N/A System.err.println("\nRegression test for bug/rfe 4183169\n");
0N/A
0N/A try {
0N/A TestLibrary.suggestSecurityManager(
0N/A "java.rmi.RMISecurityManager");
0N/A
0N/A // start an rmid.
0N/A RMID.removeLog();
0N/A rmid = RMID.createRMID();
0N/A
0N/A // rmid needs to run with a security manager that
0N/A // simulates a log problem; rmid should also snapshot
0N/A // quickly.
0N/A rmid.addOptions(new String[] {
0N/A "-Djava.security.manager=TestSecurityManager",
0N/A "-Dsun.rmi.activation.snapshotInterval=1"});
0N/A
0N/A // rmid.addArguments(new String[] {
0N/A // "-C-Djava.rmi.server.logCalls=true"});
0N/A
0N/A rmid.start();
0N/A
0N/A // Ensure that activation groups run with the correct
0N/A // security manager.
0N/A //
0N/A Properties p = new Properties();
0N/A p.put("java.security.policy",
0N/A TestParams.defaultGroupPolicy);
0N/A p.put("java.security.manager",
0N/A "java.lang.SecurityManager");
0N/A
0N/A System.err.println("activation group will be created " +
0N/A "in a new VM");
0N/A ActivationGroupDesc groupDesc =
0N/A new ActivationGroupDesc(p, null);
0N/A ActivationSystem system = ActivationGroup.getSystem();
0N/A ActivationGroupID groupID = system.registerGroup(groupDesc);
0N/A
0N/A System.err.println("registering activatable");
0N/A ActivationDesc desc = new ActivationDesc
0N/A (groupID, "ShutdownGracefully", null, null);
0N/A registering = (RegisteringActivatable)
0N/A Activatable.register(desc);
0N/A
0N/A System.err.println("activate and deactivate object " +
0N/A "via method call");
0N/A registering.shutdown();
0N/A
0N/A /*
0N/A * the security manager rmid is running with will stop
0N/A * rmid from writing to its log files; in 1.2.x this would
0N/A * have caused rmid to have thrown a runtime exception and
0N/A * continue running in an unstable state. With the fix
0N/A * for 4183169, rmid should shutdown gracefully instead.
0N/A */
0N/A
0N/A /*
0N/A * register another activatable with a new group id; rmid
0N/A * should not recover from this... I use two
0N/A * registrations to more closely simulate the environment
0N/A * in which the bug was found. In java versions with out
0N/A * the appropriate bug fix, rmid would hide a
0N/A * NullPointerException in this circumstance.
0N/A */
0N/A p.put("dummyname", "dummyvalue");
0N/A groupDesc = new ActivationGroupDesc(p, null);
0N/A ActivationGroupID secondGroupID =
0N/A system.registerGroup(groupDesc);
0N/A desc = new ActivationDesc(secondGroupID,
0N/A "ShutdownGracefully", null, null);
0N/A
0N/A try {
0N/A registering = (RegisteringActivatable)
0N/A Activatable.register(desc);
0N/A
0N/A System.err.println("second activate and deactivate " +
0N/A "object via method call");
0N/A } catch (ActivationException e) {
0N/A System.err.println("received exception from registration " +
0N/A "call that should have failed...");
0N/A }
0N/A
0N/A /*
0N/A * no longer needed because the security manager
0N/A * throws an exception during snapshot
0N/A */
0N/A /*
0N/A try {
0N/A registering.shutdown();
0N/A
0N/A System.err.println("received exception from remote " +
0N/A "call that should have failed...");
0N/A } catch (RemoteException e) {
0N/A }
0N/A */
0N/A
0N/A } catch (Exception e) {
0N/A TestLibrary.bomb("\nfailure: unexpected exception ", e);
0N/A } finally {
0N/A try {
0N/A Thread.sleep(4000);
0N/A } catch (InterruptedException e) {
0N/A }
0N/A
0N/A registering = null;
0N/A
0N/A // Need to make sure that rmid goes away by itself
5740N/A JavaVM rmidProcess = rmid;
0N/A if (rmidProcess != null) {
0N/A try {
0N/A Runnable waitThread =
0N/A new ShutdownDetectThread(rmidProcess);
0N/A
0N/A synchronized (waitThread) {
0N/A (new Thread(waitThread)).start();
0N/A waitThread.wait(SHUTDOWN_TIMEOUT);
0N/A System.err.println("rmid has shutdown");
0N/A
0N/A if (!rmidDone) {
0N/A // ensure that this rmid does not infect
0N/A // other tests.
0N/A rmidProcess.destroy();
0N/A TestLibrary.bomb("rmid did not shutdown " +
0N/A "gracefully in time");
0N/A }
0N/A }
0N/A } catch (Exception e) {
0N/A TestLibrary.bomb("exception waiting for rmid " +
0N/A "to shut down");
0N/A }
0N/A }
0N/A // else rmid should be down
0N/A }
0N/A
0N/A System.err.println
0N/A ("\nsuccess: ShutdownGracefully test passed ");
0N/A }
0N/A
0N/A private static boolean rmidDone = false;
0N/A
0N/A /**
0N/A * class that waits for rmid to exit
0N/A */
0N/A private static class ShutdownDetectThread implements Runnable {
5740N/A private JavaVM rmidProcess = null;
0N/A
5740N/A ShutdownDetectThread(JavaVM rmidProcess) {
0N/A this.rmidProcess = rmidProcess;
0N/A }
0N/A public void run() {
0N/A System.err.println("waiting for rmid to shutdown");
0N/A
0N/A try {
0N/A rmidProcess.waitFor();
0N/A } catch (InterruptedException e) {
0N/A // should not happen
0N/A }
0N/A
0N/A synchronized (this) {
0N/A // notify parent thread when rmid has exited
0N/A this.notify();
0N/A rmidDone = true;
0N/A }
0N/A
0N/A RMID.removeLog();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * implementation of RegisteringActivatable
0N/A */
0N/A public ShutdownGracefully
0N/A (ActivationID id, MarshalledObject mo) throws RemoteException
0N/A {
0N/A // register/export anonymously
0N/A super(id, 0);
0N/A }
0N/A
0N/A /**
0N/A * Spawns a thread to deactivate the object.
0N/A */
0N/A public void shutdown() throws Exception {
0N/A (new Thread(this, "ShutdownGracefully")).start();
0N/A }
0N/A
0N/A /**
0N/A * Thread to deactivate object. First attempts to make object
0N/A * inactive (via the inactive method). If that fails (the
0N/A * object may still have pending/executing calls), then
0N/A * unexport the object forcibly.
0N/A */
0N/A public void run() {
0N/A try {
0N/A Thread.sleep(50 * 1000);
0N/A } catch (InterruptedException e) {
0N/A }
0N/A ActivationLibrary.deactivate(this, getID());
0N/A }
0N/A}