Skip to content

Commit 4cd2aa5

Browse files
authored
fix(cache): fixing a condition where the old threadexecution pool would be killed on a cache flush and never come back. (dotCMS#33805)
This code changes the H22Cache to reinit the threadpool if it has been shutdown (which happens when you do a full cache flush in dotCMS). Otherwise, when you flush cache, the pool is killed dead and the cache still tries to use it for async operations. Oh, it also adds a useful filter when dumping threads that will ignore any threads that are not dotCMS based threads, e.g. reactor and tomcat threads. ref: dotCMS#33784
1 parent d88977d commit 4cd2aa5

File tree

3 files changed

+143
-111
lines changed

3 files changed

+143
-111
lines changed
Lines changed: 92 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package com.dotcms.cmsmaintenance.ajax;
22

3+
import com.dotcms.repackage.org.directwebremoting.WebContextFactory;
4+
import com.dotmarketing.business.APILocator;
5+
import com.dotmarketing.exception.DotRuntimeException;
6+
import com.dotmarketing.exception.DotSecurityException;
7+
import com.dotmarketing.util.Logger;
8+
import com.liferay.portal.model.User;
39
import java.lang.management.LockInfo;
410
import java.lang.management.ManagementFactory;
511
import java.lang.management.MonitorInfo;
@@ -8,23 +14,13 @@
814
import java.lang.management.ThreadMXBean;
915
import java.lang.reflect.Field;
1016
import java.text.SimpleDateFormat;
11-
import java.util.ArrayList;
1217
import java.util.Date;
1318
import java.util.HashMap;
1419
import java.util.HashSet;
15-
import java.util.List;
1620
import java.util.Map;
1721
import java.util.Set;
18-
1922
import javax.servlet.http.HttpServletRequest;
2023

21-
import com.dotcms.repackage.org.directwebremoting.WebContextFactory;
22-
import com.dotmarketing.business.APILocator;
23-
import com.dotmarketing.exception.DotRuntimeException;
24-
import com.dotmarketing.exception.DotSecurityException;
25-
import com.dotmarketing.util.Logger;
26-
import com.liferay.portal.model.User;
27-
2824
/**
2925
* This class gets various system property data.
3026
* Each method collects information that might be helpful for system admins.
@@ -49,22 +45,29 @@ public boolean validateUser() {
4945
}
5046
}
5147

48+
public String[] getThreads() {
49+
return getThreads(false);
50+
}
51+
52+
5253
/**
5354
* Helper method; stringfies the ThreadInfos and returns them as a string array
5455
*/
55-
public String[] getThreads() {
56+
public String[] getThreads(boolean hideSystemThreads) {
5657
// Validate user has access to the CMS Maintenance Portlet
5758
if (!validateUser()) {
5859
throw new DotRuntimeException("User does not have access to the CMS Maintenance Portlet");
5960
}
6061

61-
ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
62+
ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
6263

63-
StringBuilder sb = new StringBuilder();
64-
sb.append( "<pre>" );
65-
sb.append("\n" + new Date() + "\n");
66-
sb.append( "Full thread dump " + System.getProperty("java.vm.name")+ " " + System.getProperty("java.runtime.version") + " (" + System.getProperty("java.vm.version") + " " + System.getProperty("java.vm.info") + "):");
67-
sb.append( "\n\n" );
64+
StringBuilder mainString = new StringBuilder();
65+
mainString.append("<pre>");
66+
mainString.append("\n" + new Date() + "\n");
67+
mainString.append("Full thread dump " + System.getProperty("java.vm.name") + " " + System.getProperty(
68+
"java.runtime.version") + " (" + System.getProperty("java.vm.version") + " " + System.getProperty(
69+
"java.vm.info") + "):");
70+
mainString.append("\n\n");
6871

6972
long[] deadLockedArray = mxBean.findDeadlockedThreads();
7073
Set<Long> deadlocks = new HashSet<>();
@@ -79,133 +82,127 @@ public String[] getThreads() {
7982
Map<Long, Thread> threadMap = new HashMap<>();
8083
for( Thread t : Thread.getAllStackTraces().keySet() ) {
8184
threadMap.put( t.getId(), t );
82-
}
85+
}
8386

8487

8588
ThreadInfo[] infos = mxBean.dumpAllThreads(true, true);
86-
89+
8790
Map<String, String> blockers = new HashMap<>();
88-
89-
90-
91-
for( ThreadInfo info : infos ) {
92-
Thread thread = threadMap.get(info.getThreadId());
91+
92+
for (ThreadInfo info : infos) {
93+
StringBuilder builder = new StringBuilder();
94+
Thread thread = threadMap.get(info.getThreadId());
9395
LockInfo lockInfo = info.getLockInfo();
9496
MonitorInfo[] monitors = info.getLockedMonitors() ;
9597
LockInfo[] locks= info.getLockedSynchronizers();
96-
97-
98-
if( thread == null ) continue;
99-
98+
99+
if (thread == null) {
100+
continue;
101+
}
102+
100103

101104
long tid = info.getThreadId();
102-
105+
103106
try{
104107
Field f = Thread.class.getDeclaredField("eetop");
105108
f.setAccessible(true);
106109
Object x = f.get(thread);
107110
tid = Long.parseLong(x.toString());
108111
}catch(Exception e){
109-
112+
110113
}
111-
112-
113-
114-
long nativeParkPointer = 0;
114+
115+
long nativeParkPointer = 0;
115116
try{
116117
Field f = Thread.class.getDeclaredField("nativeParkEventPointer");
117118
f.setAccessible(true);
118119
Object x = f.get(thread);
119120
nativeParkPointer = Long.parseLong(x.toString());
120121
}catch(Exception e){
121-
122+
122123
}
123-
124-
sb.append("\"");
125-
sb.append(info.getThreadName());
126-
sb.append("\"");
127-
sb.append(" ");
128-
sb.append(thread.isDaemon() ? "daemon " : "");
129-
sb.append(thread.isInterrupted() ? "interrupted " : "");
130-
sb.append("prio=" + thread.getPriority());
131-
sb.append(" ");
132-
sb.append("tid=" + hexMe(tid));
124+
125+
builder.append("\"");
126+
builder.append(info.getThreadName());
127+
builder.append("\"");
128+
builder.append(" ");
129+
builder.append(thread.isDaemon() ? "daemon " : "");
130+
builder.append(thread.isInterrupted() ? "interrupted " : "");
131+
builder.append("prio=" + thread.getPriority());
132+
builder.append(" ");
133+
builder.append("tid=" + hexMe(tid));
133134
if((lockInfo!=null) ){
134-
sb.append(" waiting on condition [");
135-
sb.append( hexMe(lockInfo.getIdentityHashCode()));
136-
sb.append("]");
135+
builder.append(" waiting on condition [");
136+
builder.append(hexMe(lockInfo.getIdentityHashCode()));
137+
builder.append("]");
137138
}
138-
139-
140-
Object blocker = java.util.concurrent.locks.LockSupport.getBlocker(thread);
139+
140+
Object blocker = java.util.concurrent.locks.LockSupport.getBlocker(thread);
141141
if(blocker !=null){
142142
//sb.append(" ");
143143
// sb.append("nativeParkPointer=" + hexMe(blocker.hashCode()));
144144
}
145-
146-
147145

148-
146+
builder.append("\n");
149147

150-
151-
sb.append("\n");
152-
153-
sb.append(" java.lang.Thread.State: ");
154-
sb.append(thread.getState());
148+
builder.append(" java.lang.Thread.State: ");
149+
builder.append(thread.getState());
155150
if(info.getStackTrace()!=null && info.getStackTrace().length>0){
156151
StackTraceElement first = info.getStackTrace()[0];
157152
if("sleep".equals(first.getMethodName())){
158-
sb.append(" (sleeping)");
153+
builder.append(" (sleeping)");
159154
}else if("park".equals(first.getMethodName())){
160-
sb.append(" (parking)");
155+
builder.append(" (parking)");
161156
}else if("wait".equals(first.getMethodName())){
162-
sb.append(" (on object monitor)");
157+
builder.append(" (on object monitor)");
163158
}
164159
}
165-
166-
sb.append("\n");
160+
161+
builder.append("\n");
167162
int i=0;
168163
for(StackTraceElement trace : info.getStackTrace()){
169164

170-
sb.append("\tat " + trace.toString() + "\n");
165+
builder.append("\tat " + trace.toString() + "\n");
166+
171167

172-
173168
if(i==0 && lockInfo != null){
174-
175-
if(thread.getState().equals(Thread.State.WAITING) || thread.getState().equals(Thread.State.TIMED_WAITING))
176-
sb.append("\t- waiting on " + lockInfo+ ")\n");
169+
170+
if (thread.getState().equals(Thread.State.WAITING) || thread.getState()
171+
.equals(Thread.State.TIMED_WAITING)) {
172+
builder.append("\t- waiting on " + lockInfo + ")\n");
173+
}
177174
}
178-
179-
180-
if(monitors != null){
175+
176+
if (monitors != null) {
181177
for(MonitorInfo mi : monitors){
182178
if(i==mi.getLockedStackDepth()){
183-
sb.append("\t- locked <");
184-
sb.append(hexMe(mi.getIdentityHashCode()));
185-
sb.append("> (a ");
186-
sb.append(mi.getClassName());
187-
sb.append(")\n");
179+
builder.append("\t- locked <");
180+
builder.append(hexMe(mi.getIdentityHashCode()));
181+
builder.append("> (a ");
182+
builder.append(mi.getClassName());
183+
builder.append(")\n");
188184
}
189-
190-
}
191-
}
192-
193-
i++;
194-
}
195185

186+
}
187+
}
196188

189+
i++;
190+
}
197191

198-
sb.append( "\n" );
192+
builder.append("\n");
199193

200194
if( deadlocks.contains(info.getThreadId()) ) {
201-
sb.append( " ** Deadlocked **" );
202-
sb.append( "\n" );
195+
builder.append(" ** Deadlocked **");
196+
builder.append("\n");
203197
}
204198

205-
sb.append( "\n" );
199+
builder.append("\n");
200+
if (!hideSystemThreads || builder.indexOf("com.dotmarketing") > 1 || builder.indexOf("com.dotcms") > 1) {
201+
mainString.append(builder.toString());
202+
}
206203
}
207-
sb.append( "</pre>" );
208-
return new String[] {sb.toString()};
204+
mainString.append("</pre>");
205+
return new String[]{mainString.toString()};
209206

210207
} // end of getThreadArray method
211208

@@ -244,10 +241,10 @@ public Map<String, String> getSysProps(){
244241
return sysProps;
245242
}
246243

247-
248-
private String hexMe(long x){
249-
250-
return String.format("0x%016X", x).toLowerCase();
251-
252-
}
244+
245+
private String hexMe(long x) {
246+
247+
return String.format("0x%016X", x).toLowerCase();
248+
249+
}
253250
}

0 commit comments

Comments
 (0)