49 * shuts down in a graceful manner without any explicit request to do |
50 * shuts down in a graceful manner without any explicit request to do |
50 * so. The test will not exit for 400 seconds if rmid does not exit |
51 * so. The test will not exit for 400 seconds if rmid does not exit |
51 * (after that time, the test will fail). |
52 * (after that time, the test will fail). |
52 */ |
53 */ |
53 public class ShutdownGracefully |
54 public class ShutdownGracefully |
54 extends Activatable implements Runnable, RegisteringActivatable |
55 extends Activatable implements RegisteringActivatable |
55 { |
56 { |
56 private static RegisteringActivatable registering = null; |
57 private static RegisteringActivatable registering = null; |
57 |
58 |
58 private final static long SHUTDOWN_TIMEOUT = 400 * 1000; |
59 private final static long SHUTDOWN_TIMEOUT = 400 * 1000; |
59 |
60 |
60 public static void main(String args[]) { |
61 public static void main(String args[]) { |
61 |
62 |
62 RMID rmid = null; |
63 RMID rmid = null; |
63 |
64 |
|
65 // Save exception if there is a exception or expected behavior |
|
66 Exception exception = null; |
64 System.err.println("\nRegression test for bug/rfe 4183169\n"); |
67 System.err.println("\nRegression test for bug/rfe 4183169\n"); |
65 |
68 |
66 try { |
69 try { |
67 TestLibrary.suggestSecurityManager( |
70 TestLibrary.suggestSecurityManager( |
68 "java.rmi.RMISecurityManager"); |
71 "java.rmi.RMISecurityManager"); |
130 ActivationGroupID secondGroupID = |
133 ActivationGroupID secondGroupID = |
131 system.registerGroup(groupDesc); |
134 system.registerGroup(groupDesc); |
132 desc = new ActivationDesc(secondGroupID, |
135 desc = new ActivationDesc(secondGroupID, |
133 "ShutdownGracefully", null, null); |
136 "ShutdownGracefully", null, null); |
134 |
137 |
|
138 /* |
|
139 * registration request is expected to be failed. succeeded case |
|
140 * should be recorded. And raise error after clean up rmid. |
|
141 */ |
135 try { |
142 try { |
136 registering = (RegisteringActivatable) |
143 registering = (RegisteringActivatable) |
137 Activatable.register(desc); |
144 Activatable.register(desc); |
138 |
145 System.err.println("The registration request succeeded unexpectedly"); |
139 System.err.println("second activate and deactivate " + |
146 exception = new RuntimeException("The registration request succeeded unexpectedly"); |
140 "object via method call"); |
|
141 } catch (ActivationException e) { |
147 } catch (ActivationException e) { |
142 System.err.println("received exception from registration " + |
148 System.err.println("received exception from registration " + |
143 "call that should have failed..."); |
149 "call that should have failed..."); |
144 } |
150 // Need wait rmid process terminates. |
145 |
|
146 /* |
|
147 * no longer needed because the security manager |
|
148 * throws an exception during snapshot |
|
149 */ |
|
150 /* |
|
151 try { |
|
152 registering.shutdown(); |
|
153 |
|
154 System.err.println("received exception from remote " + |
|
155 "call that should have failed..."); |
|
156 } catch (RemoteException e) { |
|
157 } |
|
158 */ |
|
159 |
|
160 } catch (Exception e) { |
|
161 TestLibrary.bomb("\nfailure: unexpected exception ", e); |
|
162 } finally { |
|
163 try { |
|
164 Thread.sleep(4000); |
|
165 } catch (InterruptedException e) { |
|
166 } |
|
167 |
|
168 registering = null; |
|
169 |
|
170 // Need to make sure that rmid goes away by itself |
|
171 JavaVM rmidProcess = rmid; |
|
172 if (rmidProcess != null) { |
|
173 try { |
151 try { |
174 Runnable waitThread = |
152 int exitCode = rmid.waitFor(SHUTDOWN_TIMEOUT); |
175 new ShutdownDetectThread(rmidProcess); |
153 System.err.println("RMID has exited gracefully with exitcode:" + exitCode); |
176 |
154 rmid = null; |
177 synchronized (waitThread) { |
155 } catch (TimeoutException te) { |
178 (new Thread(waitThread)).start(); |
156 System.err.println("RMID process has not exited in given time"); |
179 waitThread.wait(SHUTDOWN_TIMEOUT); |
157 exception = te; |
180 System.err.println("rmid has shutdown"); |
|
181 |
|
182 if (!rmidDone) { |
|
183 // ensure that this rmid does not infect |
|
184 // other tests. |
|
185 rmidProcess.destroy(); |
|
186 TestLibrary.bomb("rmid did not shutdown " + |
|
187 "gracefully in time"); |
|
188 } |
|
189 } |
|
190 } catch (Exception e) { |
|
191 TestLibrary.bomb("exception waiting for rmid " + |
|
192 "to shut down"); |
|
193 } |
158 } |
194 } |
159 } |
195 // else rmid should be down |
160 } catch (Exception e) { |
|
161 System.err.println("Exception thrown:" + e); |
|
162 exception = e; |
|
163 } finally { |
|
164 if (rmid != null) |
|
165 rmid.destroy(); |
196 } |
166 } |
197 |
167 if (exception != null) |
198 System.err.println |
168 TestLibrary.bomb("\nexception thrown in test: ", exception); |
199 ("\nsuccess: ShutdownGracefully test passed "); |
|
200 } |
|
201 |
|
202 private static boolean rmidDone = false; |
|
203 |
|
204 /** |
|
205 * class that waits for rmid to exit |
|
206 */ |
|
207 private static class ShutdownDetectThread implements Runnable { |
|
208 private JavaVM rmidProcess = null; |
|
209 |
|
210 ShutdownDetectThread(JavaVM rmidProcess) { |
|
211 this.rmidProcess = rmidProcess; |
|
212 } |
|
213 public void run() { |
|
214 System.err.println("waiting for rmid to shutdown"); |
|
215 |
|
216 try { |
|
217 rmidProcess.waitFor(); |
|
218 } catch (InterruptedException e) { |
|
219 // should not happen |
|
220 } |
|
221 |
|
222 synchronized (this) { |
|
223 // notify parent thread when rmid has exited |
|
224 this.notify(); |
|
225 rmidDone = true; |
|
226 } |
|
227 |
|
228 RMID.removeLog(); |
|
229 } |
|
230 } |
169 } |
231 |
170 |
232 /** |
171 /** |
233 * implementation of RegisteringActivatable |
172 * implementation of RegisteringActivatable |
234 */ |
173 */ |
238 // register/export anonymously |
177 // register/export anonymously |
239 super(id, 0); |
178 super(id, 0); |
240 } |
179 } |
241 |
180 |
242 /** |
181 /** |
243 * Spawns a thread to deactivate the object. |
182 * Deactivates the object. We need to unexport forcibly because this call |
|
183 * in-progress on this object, which is the same object that we are trying |
|
184 * to deactivate. |
244 */ |
185 */ |
245 public void shutdown() throws Exception { |
186 public void shutdown() throws Exception { |
246 (new Thread(this, "ShutdownGracefully")).start(); |
187 Activatable.unexportObject(this, true); |
247 } |
|
248 |
|
249 /** |
|
250 * Thread to deactivate object. First attempts to make object |
|
251 * inactive (via the inactive method). If that fails (the |
|
252 * object may still have pending/executing calls), then |
|
253 * unexport the object forcibly. |
|
254 */ |
|
255 public void run() { |
|
256 try { |
|
257 Thread.sleep(50 * 1000); |
|
258 } catch (InterruptedException e) { |
|
259 } |
|
260 ActivationLibrary.deactivate(this, getID()); |
188 ActivationLibrary.deactivate(this, getID()); |
261 } |
189 } |
262 } |
190 } |