]> git.argeo.org Git - lgpl/argeo-commons.git/blob - GogoShellKiller.java
940fc8d9fcb37d878335b01b5b2a55869f704f7f
[lgpl/argeo-commons.git] / GogoShellKiller.java
1 package org.argeo.cms.internal.kernel;
2
3 /**
4 * Workaround for killing Gogo shell by system shutdown.
5 *
6 * @see https://issues.apache.org/jira/browse/FELIX-4208
7 */
8 class GogoShellKiller extends Thread {
9
10 public GogoShellKiller() {
11 super("Gogo Shell Killer");
12 setDaemon(true);
13 }
14
15 @Override
16 public void run() {
17 ThreadGroup rootTg = getRootThreadGroup(null);
18 Thread gogoShellThread = findGogoShellThread(rootTg);
19 if (gogoShellThread == null)
20 return;
21 while (getNonDaemonCount(rootTg) > 2) {
22 try {
23 Thread.sleep(100);
24 } catch (InterruptedException e) {
25 // silent
26 }
27 }
28 gogoShellThread = findGogoShellThread(rootTg);
29 if (gogoShellThread == null)
30 return;
31 // No non-deamon threads left, forcibly halting the VM
32 Runtime.getRuntime().halt(0);
33 }
34
35 private ThreadGroup getRootThreadGroup(ThreadGroup tg) {
36 if (tg == null)
37 tg = Thread.currentThread().getThreadGroup();
38 if (tg.getParent() == null)
39 return tg;
40 else
41 return getRootThreadGroup(tg.getParent());
42 }
43
44 private int getNonDaemonCount(ThreadGroup rootThreadGroup) {
45 Thread[] threads = new Thread[rootThreadGroup.activeCount()];
46 rootThreadGroup.enumerate(threads);
47 int nonDameonCount = 0;
48 for (Thread t : threads)
49 if (t != null && !t.isDaemon())
50 nonDameonCount++;
51 return nonDameonCount;
52 }
53
54 private Thread findGogoShellThread(ThreadGroup rootThreadGroup) {
55 Thread[] threads = new Thread[rootThreadGroup.activeCount()];
56 rootThreadGroup.enumerate(threads, true);
57 for (Thread thread : threads) {
58 if (thread.getName().equals("Gogo shell"))
59 return thread;
60 }
61 return null;
62 }
63
64 }