Skip to content

Commit 4ccd215

Browse files
committed
HBASE-26087 JVM crash when displaying RPC params by MonitoredRPCHandler (#3489)
Signed-off-by: stack <[email protected]>
1 parent d99ca37 commit 4ccd215

File tree

2 files changed

+82
-5
lines changed

2 files changed

+82
-5
lines changed

hbase-server/src/main/java/org/apache/hadoop/hbase/monitoring/MonitoredRPCHandlerImpl.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@
2222
import java.util.HashMap;
2323
import java.util.Map;
2424

25-
import org.apache.yetus.audience.InterfaceAudience;
2625
import org.apache.hadoop.hbase.client.Operation;
2726
import org.apache.hadoop.hbase.util.Bytes;
2827
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
28+
29+
import org.apache.yetus.audience.InterfaceAudience;
2930
import org.apache.hbase.thirdparty.com.google.protobuf.Message;
3031

3132
/**
@@ -43,6 +44,8 @@ public class MonitoredRPCHandlerImpl extends MonitoredTaskImpl
4344
private String methodName = "";
4445
private Object [] params = {};
4546
private Message packet;
47+
private boolean snapshot = false;
48+
private Map<String, Object> callInfoMap = new HashMap<>();
4649

4750
public MonitoredRPCHandlerImpl() {
4851
super();
@@ -53,11 +56,14 @@ public MonitoredRPCHandlerImpl() {
5356

5457
@Override
5558
public synchronized MonitoredRPCHandlerImpl clone() {
56-
return (MonitoredRPCHandlerImpl) super.clone();
59+
MonitoredRPCHandlerImpl clone = (MonitoredRPCHandlerImpl) super.clone();
60+
clone.callInfoMap = generateCallInfoMap();
61+
clone.snapshot = true;
62+
return clone;
5763
}
5864

5965
/**
60-
* Gets the status of this handler; if it is currently servicing an RPC,
66+
* Gets the status of this handler; if it is currently servicing an RPC,
6167
* this status will include the RPC information.
6268
* @return a String describing the current status.
6369
*/
@@ -233,6 +239,10 @@ public synchronized void markComplete(String status) {
233239

234240
@Override
235241
public synchronized Map<String, Object> toMap() {
242+
return this.snapshot ? this.callInfoMap : generateCallInfoMap();
243+
}
244+
245+
private Map<String, Object> generateCallInfoMap() {
236246
// only include RPC info if the Handler is actively servicing an RPC call
237247
Map<String, Object> map = super.toMap();
238248
if (getState() != State.RUNNING) {

hbase-server/src/test/java/org/apache/hadoop/hbase/monitoring/TestTaskMonitor.java

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@
1717
*/
1818
package org.apache.hadoop.hbase.monitoring;
1919

20-
import static org.junit.Assert.*;
21-
20+
import static org.junit.Assert.assertEquals;
21+
import static org.junit.Assert.assertNotEquals;
22+
import static org.junit.Assert.assertTrue;
23+
import static org.junit.Assert.fail;
2224
import java.util.ArrayList;
2325
import java.util.List;
26+
import java.util.Map;
2427
import java.util.concurrent.atomic.AtomicBoolean;
2528
import org.apache.hadoop.conf.Configuration;
2629
import org.apache.hadoop.hbase.HBaseClassTestRule;
@@ -34,9 +37,12 @@
3437
import org.junit.ClassRule;
3538
import org.junit.Test;
3639
import org.junit.experimental.categories.Category;
40+
import org.slf4j.Logger;
41+
import org.slf4j.LoggerFactory;
3742

3843
@Category({MiscTests.class, SmallTests.class})
3944
public class TestTaskMonitor {
45+
private static final Logger LOG = LoggerFactory.getLogger(TestTaskMonitor.class);
4046

4147
@ClassRule
4248
public static final HBaseClassTestRule CLASS_RULE =
@@ -226,5 +232,66 @@ public void testStatusJournal() {
226232
assertEquals("status3", task.getStatusJournal().get(1).getStatus());
227233
tm.shutdown();
228234
}
235+
236+
@Test
237+
public void testClone() throws Exception {
238+
MonitoredRPCHandlerImpl monitor = new MonitoredRPCHandlerImpl();
239+
monitor.abort("abort RPC");
240+
TestParam testParam = new TestParam("param1");
241+
monitor.setRPC("method1", new Object[]{ testParam }, 0);
242+
MonitoredRPCHandlerImpl clone = monitor.clone();
243+
assertEquals(clone.getDescription(), monitor.getDescription());
244+
assertEquals(clone.getState(), monitor.getState());
245+
assertEquals(clone.getStatus(), monitor.getStatus());
246+
assertEquals(clone.toString(), monitor.toString());
247+
assertEquals(clone.toMap(), monitor.toMap());
248+
assertEquals(clone.toJSON(), monitor.toJSON());
249+
250+
// mark complete and make param dirty
251+
monitor.markComplete("complete RPC");
252+
testParam.setParam("dirtyParam");
253+
assertEquals(clone.getDescription(), monitor.getDescription());
254+
assertNotEquals(clone.getState(), monitor.getState());
255+
assertNotEquals(clone.getStatus(), monitor.getStatus());
256+
monitor.setState(MonitoredTask.State.RUNNING);
257+
try {
258+
// when markComplete, the param in monitor is set null, so toMap should fail here
259+
monitor.toMap();
260+
fail("Should not call toMap successfully, because param=null");
261+
} catch (Exception e) {
262+
}
263+
// the param of clone monitor should not be dirty
264+
assertNotEquals("[dirtyString]",
265+
String.valueOf(((Map<String, Object>) clone.toMap().get("rpcCall")).get("params")));
266+
267+
monitor.resume("resume");
268+
monitor.setRPC("method2", new Object[]{new TestParam("param2")}, 1);
269+
assertNotEquals(((Map<String, Object>) clone.toMap().get("rpcCall")).get("params"),
270+
((Map<String, Object>) monitor.toMap().get("rpcCall")).get(
271+
"params"));
272+
LOG.info(String.valueOf(clone.toMap()));
273+
LOG.info(String.valueOf(monitor.toMap()));
274+
assertNotEquals(clone.toString(), monitor.toString());
275+
assertNotEquals(clone.getRPCQueueTime(), monitor.getRPCQueueTime());
276+
assertNotEquals(clone.toMap(), monitor.toMap());
277+
assertNotEquals(clone.toJSON(), monitor.toJSON());
278+
}
279+
280+
private class TestParam {
281+
public String param = null;
282+
283+
public TestParam(String param) {
284+
this.param = param;
285+
}
286+
287+
public void setParam(String param) {
288+
this.param = param;
289+
}
290+
291+
@Override
292+
public String toString() {
293+
return param;
294+
}
295+
}
229296
}
230297

0 commit comments

Comments
 (0)