194 |
SecurityManager sm = securityManager; // Be thread-safe! |
SecurityManager sm = securityManager; // Be thread-safe! |
195 |
if (sm != null) |
if (sm != null) |
196 |
sm.checkExit(status); |
sm.checkExit(status); |
197 |
|
|
198 |
|
if(runShutdownHooks()) |
199 |
|
halt(status); |
200 |
|
|
201 |
|
synchronized (libpath) |
202 |
|
{ |
203 |
|
if (shutdownHooks != null) |
204 |
|
{ |
205 |
|
shutdownHooks.remove(Thread.currentThread()); |
206 |
|
} |
207 |
|
} |
208 |
|
|
209 |
|
while (true) |
210 |
|
try |
211 |
|
{ |
212 |
|
exitSequence.join(); |
213 |
|
} |
214 |
|
catch (InterruptedException e) |
215 |
|
{ |
216 |
|
// Ignore, we've suspended indefinitely to let all shutdown |
217 |
|
// hooks complete, and to let any non-zero exits through, because |
218 |
|
// this is a duplicate call to exit(0). |
219 |
|
} |
220 |
|
} |
221 |
|
|
222 |
|
/** |
223 |
|
* On first invocation, run all the shutdown hooks and return true. |
224 |
|
* Any subsequent invocations will simply return false. |
225 |
|
* |
226 |
|
* @return was the current thread the first one to call this method? |
227 |
|
*/ |
228 |
|
private boolean runShutdownHooks() |
229 |
|
{ |
230 |
boolean first = false; |
boolean first = false; |
231 |
synchronized (libpath) // Synch on libpath, not this, to avoid deadlock. |
synchronized (libpath) // Synch on libpath, not this, to avoid deadlock. |
232 |
{ |
{ |
291 |
// this should be run on every object. |
// this should be run on every object. |
292 |
runFinalization(); |
runFinalization(); |
293 |
} |
} |
294 |
else |
return first; |
|
synchronized (libpath) |
|
|
{ |
|
|
if (shutdownHooks != null) |
|
|
{ |
|
|
shutdownHooks.remove(Thread.currentThread()); |
|
|
status = 0; // Change status to enter indefinite wait. |
|
|
} |
|
|
} |
|
|
|
|
|
if (first || status > 0) |
|
|
halt(status); |
|
|
while (true) |
|
|
try |
|
|
{ |
|
|
exitSequence.join(); |
|
|
} |
|
|
catch (InterruptedException e) |
|
|
{ |
|
|
// Ignore, we've suspended indefinitely to let all shutdown |
|
|
// hooks complete, and to let any non-zero exits through, because |
|
|
// this is a duplicate call to exit(0). |
|
|
} |
|
295 |
} |
} |
296 |
|
|
297 |
/** |
/** |