--- old/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java 2014-02-12 12:57:55.000000000 +0800 +++ new/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java 2014-02-12 12:57:55.000000000 +0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. 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 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4183169 + * @bug 4183169 8032050 * @summary Minor problem with the way ReliableLog handles IOExceptions. * * @author Laird Dornin; code borrowed from Ann Wollrath @@ -36,6 +36,7 @@ import java.rmi.activation.*; import java.rmi.*; import java.util.Properties; +import java.util.concurrent.TimeoutException; /** * The test creates an rmid with a special security manager. After @@ -51,7 +52,7 @@ * (after that time, the test will fail). */ public class ShutdownGracefully - extends Activatable implements Runnable, RegisteringActivatable + extends Activatable implements RegisteringActivatable { private static RegisteringActivatable registering = null; @@ -132,100 +133,32 @@ desc = new ActivationDesc(secondGroupID, "ShutdownGracefully", null, null); + /* + * registration request is expected to be failed. succeeded case + * should be recorded. And raise error after clean up rmid. + */ + boolean isRegisterSucceed = false; try { registering = (RegisteringActivatable) Activatable.register(desc); - System.err.println("second activate and deactivate " + - "object via method call"); + isRegisterSucceed = true; } 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) { - } - */ - + int exitCode = rmid.waitFor(SHUTDOWN_TIMEOUT); + System.err.println("RMID has exited gracefully with exitcode:" + exitCode); + rmid = null; + if(isRegisterSucceed) + TestLibrary.bomb("\nfailure: The registration request succeeded unexpectedly"); + } catch (TimeoutException e) { + TestLibrary.bomb("\nfailure: RMID hasn't exited gracefuuly in expected time"); } 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 - JavaVM rmidProcess = rmid; - 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 JavaVM rmidProcess = null; - - ShutdownDetectThread(JavaVM 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(); + if (rmid != null) + rmid.destroy(); } } @@ -240,23 +173,12 @@ } /** - * Spawns a thread to deactivate the object. + * Deactivates the object. We need to unexport forcibly because this call + * in-progress on this object, which is the same object that we are trying + * to deactivate. */ 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) { - } + Activatable.unexportObject(this, true); ActivationLibrary.deactivate(this, getID()); } } --- old/test/java/rmi/testlibrary/JavaVM.java 2014-02-12 12:57:56.000000000 +0800 +++ new/test/java/rmi/testlibrary/JavaVM.java 2014-02-12 12:57:56.000000000 +0800 @@ -26,6 +26,7 @@ import java.io.OutputStream; import java.util.Arrays; import java.util.StringTokenizer; +import java.util.concurrent.TimeoutException; /** * RMI regression test utility class that uses Runtime.exec to spawn a @@ -172,6 +173,41 @@ return status; } + /** + * Causes the current thread to wait the subprocess to exit, if necessary, + * until the subprocess represented by this Process object has terminated, + * or the specified waiting time elapses. + * @param timeout the maximum milliseconds to wait + * @return true if the JavaVM has exited and false if the waiting time + * elapsed before the subprocess has exited. + * @throws InterruptedException if the current thread is interrupted + * while waiting. + * @throws TimeoutException if subprocess does not end after timeout + * milliseconds passed + */ + public int waitFor(long timeout) + throws InterruptedException, TimeoutException { + if (vm == null) + throw new IllegalStateException("can't wait for JavaVM that isn't running"); + long startTime = System.currentTimeMillis(); + long rem = timeout; + + do { + try { + int status = vm.exitValue(); + outPipe.join(); + errPipe.join(); + return status; + } catch (IllegalThreadStateException ex) { + if (rem > 0) { + Thread.sleep(Math.min(rem, 100)); + } + } + rem = timeout - (System.currentTimeMillis() - startTime); + } while (rem > 0); + throw new TimeoutException(); + } + /** * Starts the subprocess, waits for it to exit, and returns its exit status. */