8032050: Clean up for java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java

Reviewed-by: smarks
This commit is contained in:
Tristan Yan 2014-02-15 10:23:07 +08:00
parent 7cb914ecd2
commit 05263ad736
2 changed files with 66 additions and 103 deletions
jdk/test/java/rmi
activation/Activatable/shutdownGracefully
testlibrary

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,7 +22,7 @@
*/ */
/* @test /* @test
* @bug 4183169 * @bug 4183169 8032050
* @summary Minor problem with the way ReliableLog handles IOExceptions. * @summary Minor problem with the way ReliableLog handles IOExceptions.
* *
* @author Laird Dornin; code borrowed from Ann Wollrath * @author Laird Dornin; code borrowed from Ann Wollrath
@ -36,6 +36,7 @@
import java.rmi.activation.*; import java.rmi.activation.*;
import java.rmi.*; import java.rmi.*;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.TimeoutException;
/** /**
* The test creates an rmid with a special security manager. After * The test creates an rmid with a special security manager. After
@ -51,7 +52,7 @@ import java.util.Properties;
* (after that time, the test will fail). * (after that time, the test will fail).
*/ */
public class ShutdownGracefully public class ShutdownGracefully
extends Activatable implements Runnable, RegisteringActivatable extends Activatable implements RegisteringActivatable
{ {
private static RegisteringActivatable registering = null; private static RegisteringActivatable registering = null;
@ -61,6 +62,8 @@ public class ShutdownGracefully
RMID rmid = null; RMID rmid = null;
// Save exception if there is a exception or expected behavior
Exception exception = null;
System.err.println("\nRegression test for bug/rfe 4183169\n"); System.err.println("\nRegression test for bug/rfe 4183169\n");
try { try {
@ -132,101 +135,37 @@ public class ShutdownGracefully
desc = new ActivationDesc(secondGroupID, desc = new ActivationDesc(secondGroupID,
"ShutdownGracefully", null, null); "ShutdownGracefully", null, null);
/*
* registration request is expected to be failed. succeeded case
* should be recorded. And raise error after clean up rmid.
*/
try { try {
registering = (RegisteringActivatable) registering = (RegisteringActivatable)
Activatable.register(desc); Activatable.register(desc);
System.err.println("The registration request succeeded unexpectedly");
System.err.println("second activate and deactivate " + exception = new RuntimeException("The registration request succeeded unexpectedly");
"object via method call");
} catch (ActivationException e) { } catch (ActivationException e) {
System.err.println("received exception from registration " + System.err.println("received exception from registration " +
"call that should have failed..."); "call that should have failed...");
} // Need wait rmid process terminates.
/*
* 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
JavaVM rmidProcess = rmid;
if (rmidProcess != null) {
try { try {
Runnable waitThread = int exitCode = rmid.waitFor(SHUTDOWN_TIMEOUT);
new ShutdownDetectThread(rmidProcess); System.err.println("RMID has exited gracefully with exitcode:" + exitCode);
rmid = null;
synchronized (waitThread) { } catch (TimeoutException te) {
(new Thread(waitThread)).start(); System.err.println("RMID process has not exited in given time");
waitThread.wait(SHUTDOWN_TIMEOUT); exception = te;
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 } catch (Exception e) {
} System.err.println("Exception thrown:" + e);
exception = e;
System.err.println } finally {
("\nsuccess: ShutdownGracefully test passed "); if (rmid != null)
} rmid.destroy();
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 (exception != null)
TestLibrary.bomb("\nexception thrown in test: ", exception);
} }
/** /**
@ -240,23 +179,12 @@ public class ShutdownGracefully
} }
/** /**
* 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 { public void shutdown() throws Exception {
(new Thread(this, "ShutdownGracefully")).start(); Activatable.unexportObject(this, true);
}
/**
* 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()); ActivationLibrary.deactivate(this, getID());
} }
} }

@ -26,6 +26,7 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Arrays; import java.util.Arrays;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.concurrent.TimeoutException;
/** /**
* RMI regression test utility class that uses Runtime.exec to spawn a * RMI regression test utility class that uses Runtime.exec to spawn a
@ -172,6 +173,40 @@ public class JavaVM {
return status; return status;
} }
/**
* Causes the current thread to wait the vm process to exit, if necessary,
* wait until the vm process has terminated, or the specified waiting time
* elapses. Release allocated input/output after vm process has terminated.
* @param timeout the maximum milliseconds to wait.
* @return exit value for vm process.
* @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. * Starts the subprocess, waits for it to exit, and returns its exit status.
*/ */