jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,265 @@
+/*
+ * Copyright 1999 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 4183169
+ * @summary Minor problem with the way ReliableLog handles IOExceptions.
+ *
+ * @author Laird Dornin; code borrowed from Ann Wollrath
+ *
+ * @library ../../../testlibrary
+ * @build TestLibrary RMID JavaVM StreamPipe
+ * @build TestSecurityManager
+ * @build RegisteringActivatable
+ * @build ShutdownGracefully
+ * @build ShutdownGracefully_Stub
+ * @run main/othervm/policy=security.policy/timeout=700 ShutdownGracefully
+ */
+
+import java.rmi.activation.*;
+import java.rmi.*;
+import java.util.Properties;
+
+/**
+ * The test creates an rmid with a special security manager. After
+ * rmid makes two registrations (which is greater than rmid's
+ * snapshotInterval) the security manager stops allowing rmid to write
+ * to update and snapshot log files in rmid's log directory. The Test
+ * registers an Activatable object twice with different group ids.
+ * The second registration will cause rmid to have to write to a
+ * LogFile (it causes a snapshot) and the security manager will not
+ * allow the file write to happen. The test makes sure that rmid
+ * shuts down in a graceful manner without any explicit request to do
+ * so. The test will not exit for 400 seconds if rmid does not exit
+ * (after that time, the test will fail).
+ */
+public class ShutdownGracefully
+ extends Activatable implements Runnable, RegisteringActivatable
+{
+ private static RegisteringActivatable registering = null;
+
+ private final static long SHUTDOWN_TIMEOUT = 400 * 1000;
+
+ public static void main(String args[]) {
+
+ RMID rmid = null;
+
+ System.err.println("\nRegression test for bug/rfe 4183169\n");
+
+ try {
+ TestLibrary.suggestSecurityManager(
+ "java.rmi.RMISecurityManager");
+
+ // start an rmid.
+ RMID.removeLog();
+ rmid = RMID.createRMID();
+
+ // rmid needs to run with a security manager that
+ // simulates a log problem; rmid should also snapshot
+ // quickly.
+ rmid.addOptions(new String[] {
+ "-Djava.security.manager=TestSecurityManager",
+ "-Dsun.rmi.activation.snapshotInterval=1"});
+
+ // rmid.addArguments(new String[] {
+ // "-C-Djava.rmi.server.logCalls=true"});
+
+ rmid.start();
+
+ // Ensure that activation groups run with the correct
+ // security manager.
+ //
+ Properties p = new Properties();
+ p.put("java.security.policy",
+ TestParams.defaultGroupPolicy);
+ p.put("java.security.manager",
+ "java.lang.SecurityManager");
+
+ System.err.println("activation group will be created " +
+ "in a new VM");
+ ActivationGroupDesc groupDesc =
+ new ActivationGroupDesc(p, null);
+ ActivationSystem system = ActivationGroup.getSystem();
+ ActivationGroupID groupID = system.registerGroup(groupDesc);
+
+ System.err.println("registering activatable");
+ ActivationDesc desc = new ActivationDesc
+ (groupID, "ShutdownGracefully", null, null);
+ registering = (RegisteringActivatable)
+ Activatable.register(desc);
+
+ System.err.println("activate and deactivate object " +
+ "via method call");
+ registering.shutdown();
+
+ /*
+ * the security manager rmid is running with will stop
+ * rmid from writing to its log files; in 1.2.x this would
+ * have caused rmid to have thrown a runtime exception and
+ * continue running in an unstable state. With the fix
+ * for 4183169, rmid should shutdown gracefully instead.
+ */
+
+ /*
+ * register another activatable with a new group id; rmid
+ * should not recover from this... I use two
+ * registrations to more closely simulate the environment
+ * in which the bug was found. In java versions with out
+ * the appropriate bug fix, rmid would hide a
+ * NullPointerException in this circumstance.
+ */
+ p.put("dummyname", "dummyvalue");
+ groupDesc = new ActivationGroupDesc(p, null);
+ ActivationGroupID secondGroupID =
+ system.registerGroup(groupDesc);
+ desc = new ActivationDesc(secondGroupID,
+ "ShutdownGracefully", null, null);
+
+ try {
+ registering = (RegisteringActivatable)
+ Activatable.register(desc);
+
+ System.err.println("second activate and deactivate " +
+ "object via method call");
+ } catch (ActivationException e) {
+ System.err.println("received exception from registration " +
+ "call that should have failed...");
+ }
+
+ /*
+ * no longer needed because the security manager
+ * throws an exception during snapshot
+ */
+ /*
+ try {
+ registering.shutdown();
+
+ System.err.println("received exception from remote " +
+ "call that should have failed...");
+ } catch (RemoteException e) {
+ }
+ */
+
+ } catch (Exception e) {
+ TestLibrary.bomb("\nfailure: unexpected exception ", e);
+ } finally {
+ try {
+ Thread.sleep(4000);
+ } catch (InterruptedException e) {
+ }
+
+ registering = null;
+
+ // Need to make sure that rmid goes away by itself
+ Process rmidProcess = rmid.getVM();
+ if (rmidProcess != null) {
+ try {
+ Runnable waitThread =
+ new ShutdownDetectThread(rmidProcess);
+
+ synchronized (waitThread) {
+ (new Thread(waitThread)).start();
+ waitThread.wait(SHUTDOWN_TIMEOUT);
+ System.err.println("rmid has shutdown");
+
+ if (!rmidDone) {
+ // ensure that this rmid does not infect
+ // other tests.
+ rmidProcess.destroy();
+ TestLibrary.bomb("rmid did not shutdown " +
+ "gracefully in time");
+ }
+ }
+ } catch (Exception e) {
+ TestLibrary.bomb("exception waiting for rmid " +
+ "to shut down");
+ }
+ }
+ // else rmid should be down
+ }
+
+ System.err.println
+ ("\nsuccess: ShutdownGracefully test passed ");
+ }
+
+ private static boolean rmidDone = false;
+
+ /**
+ * class that waits for rmid to exit
+ */
+ private static class ShutdownDetectThread implements Runnable {
+ private Process rmidProcess = null;
+
+ ShutdownDetectThread(Process rmidProcess) {
+ this.rmidProcess = rmidProcess;
+ }
+ public void run() {
+ System.err.println("waiting for rmid to shutdown");
+
+ try {
+ rmidProcess.waitFor();
+ } catch (InterruptedException e) {
+ // should not happen
+ }
+
+ synchronized (this) {
+ // notify parent thread when rmid has exited
+ this.notify();
+ rmidDone = true;
+ }
+
+ RMID.removeLog();
+ }
+ }
+
+ /**
+ * implementation of RegisteringActivatable
+ */
+ public ShutdownGracefully
+ (ActivationID id, MarshalledObject mo) throws RemoteException
+ {
+ // register/export anonymously
+ super(id, 0);
+ }
+
+ /**
+ * Spawns a thread to deactivate the object.
+ */
+ public void shutdown() throws Exception {
+ (new Thread(this, "ShutdownGracefully")).start();
+ }
+
+ /**
+ * Thread to deactivate object. First attempts to make object
+ * inactive (via the inactive method). If that fails (the
+ * object may still have pending/executing calls), then
+ * unexport the object forcibly.
+ */
+ public void run() {
+ try {
+ Thread.sleep(50 * 1000);
+ } catch (InterruptedException e) {
+ }
+ ActivationLibrary.deactivate(this, getID());
+ }
+}