blob: 48035fb6de5c5199c47b29432c18c905171e3957 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1999 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/* @test
25 * @bug 4183169
26 * @summary Minor problem with the way ReliableLog handles IOExceptions.
27 *
28 * @author Laird Dornin; code borrowed from Ann Wollrath
29 *
30 * @library ../../../testlibrary
31 * @build TestLibrary RMID JavaVM StreamPipe
32 * @build TestSecurityManager
33 * @build RegisteringActivatable
34 * @build ShutdownGracefully
35 * @build ShutdownGracefully_Stub
36 * @run main/othervm/policy=security.policy/timeout=700 ShutdownGracefully
37 */
38
39import java.rmi.activation.*;
40import java.rmi.*;
41import java.util.Properties;
42
43/**
44 * The test creates an rmid with a special security manager. After
45 * rmid makes two registrations (which is greater than rmid's
46 * snapshotInterval) the security manager stops allowing rmid to write
47 * to update and snapshot log files in rmid's log directory. The Test
48 * registers an Activatable object twice with different group ids.
49 * The second registration will cause rmid to have to write to a
50 * LogFile (it causes a snapshot) and the security manager will not
51 * allow the file write to happen. The test makes sure that rmid
52 * shuts down in a graceful manner without any explicit request to do
53 * so. The test will not exit for 400 seconds if rmid does not exit
54 * (after that time, the test will fail).
55 */
56public class ShutdownGracefully
57 extends Activatable implements Runnable, RegisteringActivatable
58{
59 private static RegisteringActivatable registering = null;
60
61 private final static long SHUTDOWN_TIMEOUT = 400 * 1000;
62
63 public static void main(String args[]) {
64
65 RMID rmid = null;
66
67 System.err.println("\nRegression test for bug/rfe 4183169\n");
68
69 try {
70 TestLibrary.suggestSecurityManager(
71 "java.rmi.RMISecurityManager");
72
73 // start an rmid.
74 RMID.removeLog();
75 rmid = RMID.createRMID();
76
77 // rmid needs to run with a security manager that
78 // simulates a log problem; rmid should also snapshot
79 // quickly.
80 rmid.addOptions(new String[] {
81 "-Djava.security.manager=TestSecurityManager",
82 "-Dsun.rmi.activation.snapshotInterval=1"});
83
84 // rmid.addArguments(new String[] {
85 // "-C-Djava.rmi.server.logCalls=true"});
86
87 rmid.start();
88
89 // Ensure that activation groups run with the correct
90 // security manager.
91 //
92 Properties p = new Properties();
93 p.put("java.security.policy",
94 TestParams.defaultGroupPolicy);
95 p.put("java.security.manager",
96 "java.lang.SecurityManager");
97
98 System.err.println("activation group will be created " +
99 "in a new VM");
100 ActivationGroupDesc groupDesc =
101 new ActivationGroupDesc(p, null);
102 ActivationSystem system = ActivationGroup.getSystem();
103 ActivationGroupID groupID = system.registerGroup(groupDesc);
104
105 System.err.println("registering activatable");
106 ActivationDesc desc = new ActivationDesc
107 (groupID, "ShutdownGracefully", null, null);
108 registering = (RegisteringActivatable)
109 Activatable.register(desc);
110
111 System.err.println("activate and deactivate object " +
112 "via method call");
113 registering.shutdown();
114
115 /*
116 * the security manager rmid is running with will stop
117 * rmid from writing to its log files; in 1.2.x this would
118 * have caused rmid to have thrown a runtime exception and
119 * continue running in an unstable state. With the fix
120 * for 4183169, rmid should shutdown gracefully instead.
121 */
122
123 /*
124 * register another activatable with a new group id; rmid
125 * should not recover from this... I use two
126 * registrations to more closely simulate the environment
127 * in which the bug was found. In java versions with out
128 * the appropriate bug fix, rmid would hide a
129 * NullPointerException in this circumstance.
130 */
131 p.put("dummyname", "dummyvalue");
132 groupDesc = new ActivationGroupDesc(p, null);
133 ActivationGroupID secondGroupID =
134 system.registerGroup(groupDesc);
135 desc = new ActivationDesc(secondGroupID,
136 "ShutdownGracefully", null, null);
137
138 try {
139 registering = (RegisteringActivatable)
140 Activatable.register(desc);
141
142 System.err.println("second activate and deactivate " +
143 "object via method call");
144 } catch (ActivationException e) {
145 System.err.println("received exception from registration " +
146 "call that should have failed...");
147 }
148
149 /*
150 * no longer needed because the security manager
151 * throws an exception during snapshot
152 */
153 /*
154 try {
155 registering.shutdown();
156
157 System.err.println("received exception from remote " +
158 "call that should have failed...");
159 } catch (RemoteException e) {
160 }
161 */
162
163 } catch (Exception e) {
164 TestLibrary.bomb("\nfailure: unexpected exception ", e);
165 } finally {
166 try {
167 Thread.sleep(4000);
168 } catch (InterruptedException e) {
169 }
170
171 registering = null;
172
173 // Need to make sure that rmid goes away by itself
174 Process rmidProcess = rmid.getVM();
175 if (rmidProcess != null) {
176 try {
177 Runnable waitThread =
178 new ShutdownDetectThread(rmidProcess);
179
180 synchronized (waitThread) {
181 (new Thread(waitThread)).start();
182 waitThread.wait(SHUTDOWN_TIMEOUT);
183 System.err.println("rmid has shutdown");
184
185 if (!rmidDone) {
186 // ensure that this rmid does not infect
187 // other tests.
188 rmidProcess.destroy();
189 TestLibrary.bomb("rmid did not shutdown " +
190 "gracefully in time");
191 }
192 }
193 } catch (Exception e) {
194 TestLibrary.bomb("exception waiting for rmid " +
195 "to shut down");
196 }
197 }
198 // else rmid should be down
199 }
200
201 System.err.println
202 ("\nsuccess: ShutdownGracefully test passed ");
203 }
204
205 private static boolean rmidDone = false;
206
207 /**
208 * class that waits for rmid to exit
209 */
210 private static class ShutdownDetectThread implements Runnable {
211 private Process rmidProcess = null;
212
213 ShutdownDetectThread(Process rmidProcess) {
214 this.rmidProcess = rmidProcess;
215 }
216 public void run() {
217 System.err.println("waiting for rmid to shutdown");
218
219 try {
220 rmidProcess.waitFor();
221 } catch (InterruptedException e) {
222 // should not happen
223 }
224
225 synchronized (this) {
226 // notify parent thread when rmid has exited
227 this.notify();
228 rmidDone = true;
229 }
230
231 RMID.removeLog();
232 }
233 }
234
235 /**
236 * implementation of RegisteringActivatable
237 */
238 public ShutdownGracefully
239 (ActivationID id, MarshalledObject mo) throws RemoteException
240 {
241 // register/export anonymously
242 super(id, 0);
243 }
244
245 /**
246 * Spawns a thread to deactivate the object.
247 */
248 public void shutdown() throws Exception {
249 (new Thread(this, "ShutdownGracefully")).start();
250 }
251
252 /**
253 * Thread to deactivate object. First attempts to make object
254 * inactive (via the inactive method). If that fails (the
255 * object may still have pending/executing calls), then
256 * unexport the object forcibly.
257 */
258 public void run() {
259 try {
260 Thread.sleep(50 * 1000);
261 } catch (InterruptedException e) {
262 }
263 ActivationLibrary.deactivate(this, getID());
264 }
265}