Lines 273-285
Link Here
|
273 |
public void destroy() { |
273 |
public void destroy() { |
274 |
shutdownExecutor(); |
274 |
shutdownExecutor(); |
275 |
super.destroy(); |
275 |
super.destroy(); |
|
|
276 |
// If the executor hasn't fully shutdown it won't be possible to |
277 |
// destroy this thread group as there will still be threads running. |
278 |
// Mark the thread group as daemon one, so that it destroys itself |
279 |
// when thread count reaches zero. |
280 |
// Synchronization on threadGroup is needed, as there is a race between |
281 |
// destroy() call from termination of the last thread in thread group |
282 |
// marked as daemon versus the explicit destroy() call. |
283 |
int threadCount = threadGroup.activeCount(); |
284 |
boolean success = false; |
276 |
try { |
285 |
try { |
277 |
threadGroup.destroy(); |
286 |
while (true) { |
278 |
} catch (IllegalThreadStateException itse) { |
287 |
int oldThreadCount = threadCount; |
279 |
// If the executor hasn't fully shutdown it won't be possible to |
288 |
synchronized (threadGroup) { |
280 |
// destroy this thread group as there will still be threads running |
289 |
if (threadCount > 0) { |
|
|
290 |
Thread.yield(); |
291 |
threadCount = threadGroup.activeCount(); |
292 |
} |
293 |
if (threadCount > 0 && threadCount != oldThreadCount) { |
294 |
// Value not stabilized. Retry. |
295 |
continue; |
296 |
} |
297 |
if (threadCount > 0) { |
298 |
threadGroup.setDaemon(true); |
299 |
} else { |
300 |
threadGroup.destroy(); |
301 |
success = true; |
302 |
} |
303 |
break; |
304 |
} |
305 |
} |
306 |
} catch (IllegalThreadStateException exception) { |
307 |
// Fall-through |
308 |
} |
309 |
if (!success) { |
281 |
log.warn(sm.getString("serverContainer.threadGroupNotDestroyed", |
310 |
log.warn(sm.getString("serverContainer.threadGroupNotDestroyed", |
282 |
threadGroup.getName())); |
311 |
threadGroup.getName(), Integer.valueOf(threadCount))); |
283 |
} |
312 |
} |
284 |
} |
313 |
} |
285 |
|
314 |
|