You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by zh...@apache.org on 2018/02/15 04:33:30 UTC
[04/30] hbase git commit: HBASE-19986 If HBaseTestClassRule timesout
a test, thread dump
HBASE-19986 If HBaseTestClassRule timesout a test, thread dump
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/c2ee82c9
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/c2ee82c9
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/c2ee82c9
Branch: refs/heads/HBASE-19064
Commit: c2ee82c9091a721e22a0eb69be17cd0217739099
Parents: 00f8877
Author: Michael Stack <st...@apache.org>
Authored: Mon Feb 12 14:00:35 2018 -0800
Committer: Michael Stack <st...@apache.org>
Committed: Mon Feb 12 15:28:40 2018 -0800
----------------------------------------------------------------------
.../apache/hadoop/hbase/HBaseClassTestRule.java | 3 +-
.../org/apache/hadoop/hbase/TestTimeout.java | 15 +-
.../hadoop/hbase/TimedOutTestsListener.java | 177 +++++++++++++++++++
.../hadoop/hbase/TimedOutTestsListener.java | 176 ------------------
pom.xml | 2 +-
5 files changed, 194 insertions(+), 179 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/c2ee82c9/hbase-common/src/test/java/org/apache/hadoop/hbase/HBaseClassTestRule.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/test/java/org/apache/hadoop/hbase/HBaseClassTestRule.java b/hbase-common/src/test/java/org/apache/hadoop/hbase/HBaseClassTestRule.java
index bcde826..b964872 100644
--- a/hbase-common/src/test/java/org/apache/hadoop/hbase/HBaseClassTestRule.java
+++ b/hbase-common/src/test/java/org/apache/hadoop/hbase/HBaseClassTestRule.java
@@ -1,4 +1,4 @@
-/**
+/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -18,6 +18,7 @@
package org.apache.hadoop.hbase;
import java.util.concurrent.TimeUnit;
+
import org.apache.hadoop.hbase.testclassification.LargeTests;
import org.apache.hadoop.hbase.testclassification.MediumTests;
import org.apache.hadoop.hbase.testclassification.SmallTests;
http://git-wip-us.apache.org/repos/asf/hbase/blob/c2ee82c9/hbase-common/src/test/java/org/apache/hadoop/hbase/TestTimeout.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/test/java/org/apache/hadoop/hbase/TestTimeout.java b/hbase-common/src/test/java/org/apache/hadoop/hbase/TestTimeout.java
index 343108e..495667c 100644
--- a/hbase-common/src/test/java/org/apache/hadoop/hbase/TestTimeout.java
+++ b/hbase-common/src/test/java/org/apache/hadoop/hbase/TestTimeout.java
@@ -18,6 +18,7 @@
package org.apache.hadoop.hbase;
import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.apache.hadoop.hbase.util.Threads;
import org.junit.ClassRule;
import org.junit.Ignore;
import org.junit.Test;
@@ -41,6 +42,18 @@ public class TestTimeout {
*/
@Ignore @Test
public void infiniteLoop() {
- while (true) {}
+ // Launch a background non-daemon thread.
+ Thread t = new Thread("HangingThread") {
+ public void run() {
+ synchronized(this) {
+ while(true) {
+ }
+ }
+ }
+ };
+ t.start();
+ while (true) {
+ // Just hang out too.
+ }
}
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/c2ee82c9/hbase-common/src/test/java/org/apache/hadoop/hbase/TimedOutTestsListener.java
----------------------------------------------------------------------
diff --git a/hbase-common/src/test/java/org/apache/hadoop/hbase/TimedOutTestsListener.java b/hbase-common/src/test/java/org/apache/hadoop/hbase/TimedOutTestsListener.java
new file mode 100644
index 0000000..d5c87f3
--- /dev/null
+++ b/hbase-common/src/test/java/org/apache/hadoop/hbase/TimedOutTestsListener.java
@@ -0,0 +1,177 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hbase;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.management.LockInfo;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MonitorInfo;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Map;
+
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+/**
+ * JUnit run listener which prints full thread dump into System.err
+ * in case a test is failed due to timeout.
+ */
+public class TimedOutTestsListener extends RunListener {
+
+ static final String TEST_TIMED_OUT_PREFIX = "test timed out after";
+
+ private static String INDENT = " ";
+
+ private final PrintWriter output;
+
+ public TimedOutTestsListener() {
+ this.output = new PrintWriter(System.err);
+ }
+
+ public TimedOutTestsListener(PrintWriter output) {
+ this.output = output;
+ }
+
+ @Override
+ public void testFailure(Failure failure) throws Exception {
+ if (failure != null && failure.getMessage() != null
+ && failure.getMessage().startsWith(TEST_TIMED_OUT_PREFIX)) {
+ output.println("====> TEST TIMED OUT. PRINTING THREAD DUMP. <====");
+ output.println();
+ output.print(buildThreadDiagnosticString());
+ }
+ output.flush();
+ }
+
+ public static String buildThreadDiagnosticString() {
+ StringWriter sw = new StringWriter();
+ PrintWriter output = new PrintWriter(sw);
+
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss,SSS");
+ output.println(String.format("Timestamp: %s", dateFormat.format(new Date())));
+ output.println();
+ output.println(buildThreadDump());
+
+ String deadlocksInfo = buildDeadlockInfo();
+ if (deadlocksInfo != null) {
+ output.println("====> DEADLOCKS DETECTED <====");
+ output.println();
+ output.println(deadlocksInfo);
+ }
+
+ return sw.toString();
+ }
+
+ static String buildThreadDump() {
+ StringBuilder dump = new StringBuilder();
+ Map<Thread, StackTraceElement[]> stackTraces = Thread.getAllStackTraces();
+ for (Map.Entry<Thread, StackTraceElement[]> e : stackTraces.entrySet()) {
+ Thread thread = e.getKey();
+ dump.append(String.format(
+ "\"%s\" %s prio=%d tid=%d %s\njava.lang.Thread.State: %s",
+ thread.getName(),
+ (thread.isDaemon() ? "daemon" : ""),
+ thread.getPriority(),
+ thread.getId(),
+ Thread.State.WAITING.equals(thread.getState()) ?
+ "in Object.wait()" : thread.getState().name().toLowerCase(Locale.ROOT),
+ Thread.State.WAITING.equals(thread.getState()) ?
+ "WAITING (on object monitor)" : thread.getState()));
+ for (StackTraceElement stackTraceElement : e.getValue()) {
+ dump.append("\n at ");
+ dump.append(stackTraceElement);
+ }
+ dump.append("\n");
+ }
+ return dump.toString();
+ }
+
+ static String buildDeadlockInfo() {
+ ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
+ long[] threadIds = threadBean.findMonitorDeadlockedThreads();
+ if (threadIds != null && threadIds.length > 0) {
+ StringWriter stringWriter = new StringWriter();
+ PrintWriter out = new PrintWriter(stringWriter);
+
+ ThreadInfo[] infos = threadBean.getThreadInfo(threadIds, true, true);
+ for (ThreadInfo ti : infos) {
+ printThreadInfo(ti, out);
+ printLockInfo(ti.getLockedSynchronizers(), out);
+ out.println();
+ }
+
+ out.close();
+ return stringWriter.toString();
+ } else {
+ return null;
+ }
+ }
+
+ private static void printThreadInfo(ThreadInfo ti, PrintWriter out) {
+ // print thread information
+ printThread(ti, out);
+
+ // print stack trace with locks
+ StackTraceElement[] stacktrace = ti.getStackTrace();
+ MonitorInfo[] monitors = ti.getLockedMonitors();
+ for (int i = 0; i < stacktrace.length; i++) {
+ StackTraceElement ste = stacktrace[i];
+ out.println(INDENT + "at " + ste.toString());
+ for (MonitorInfo mi : monitors) {
+ if (mi.getLockedStackDepth() == i) {
+ out.println(INDENT + " - locked " + mi);
+ }
+ }
+ }
+ out.println();
+ }
+
+ private static void printThread(ThreadInfo ti, PrintWriter out) {
+ out.print("\"" + ti.getThreadName() + "\"" + " Id="
+ + ti.getThreadId() + " in " + ti.getThreadState());
+ if (ti.getLockName() != null) {
+ out.print(" on lock=" + ti.getLockName());
+ }
+ if (ti.isSuspended()) {
+ out.print(" (suspended)");
+ }
+ if (ti.isInNative()) {
+ out.print(" (running in native)");
+ }
+ out.println();
+ if (ti.getLockOwnerName() != null) {
+ out.println(INDENT + " owned by " + ti.getLockOwnerName() + " Id="
+ + ti.getLockOwnerId());
+ }
+ }
+
+ private static void printLockInfo(LockInfo[] locks, PrintWriter out) {
+ out.println(INDENT + "Locked synchronizers: count = " + locks.length);
+ for (LockInfo li : locks) {
+ out.println(INDENT + " - " + li);
+ }
+ out.println();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/hbase/blob/c2ee82c9/hbase-server/src/test/java/org/apache/hadoop/hbase/TimedOutTestsListener.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/TimedOutTestsListener.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/TimedOutTestsListener.java
deleted file mode 100644
index 5beeace..0000000
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/TimedOutTestsListener.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.hbase;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.management.LockInfo;
-import java.lang.management.ManagementFactory;
-import java.lang.management.MonitorInfo;
-import java.lang.management.ThreadInfo;
-import java.lang.management.ThreadMXBean;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.Map;
-
-import org.junit.runner.notification.Failure;
-import org.junit.runner.notification.RunListener;
-
-/**
- * JUnit run listener which prints full thread dump into System.err
- * in case a test is failed due to timeout.
- */
-public class TimedOutTestsListener extends RunListener {
-
- static final String TEST_TIMED_OUT_PREFIX = "test timed out after";
-
- private static String INDENT = " ";
-
- private final PrintWriter output;
-
- public TimedOutTestsListener() {
- this.output = new PrintWriter(System.err);
- }
-
- public TimedOutTestsListener(PrintWriter output) {
- this.output = output;
- }
-
- @Override
- public void testFailure(Failure failure) throws Exception {
- if (failure != null && failure.getMessage() != null
- && failure.getMessage().startsWith(TEST_TIMED_OUT_PREFIX)) {
- output.println("====> TEST TIMED OUT. PRINTING THREAD DUMP. <====");
- output.println();
- output.print(buildThreadDiagnosticString());
- }
- }
-
- public static String buildThreadDiagnosticString() {
- StringWriter sw = new StringWriter();
- PrintWriter output = new PrintWriter(sw);
-
- DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss,SSS");
- output.println(String.format("Timestamp: %s", dateFormat.format(new Date())));
- output.println();
- output.println(buildThreadDump());
-
- String deadlocksInfo = buildDeadlockInfo();
- if (deadlocksInfo != null) {
- output.println("====> DEADLOCKS DETECTED <====");
- output.println();
- output.println(deadlocksInfo);
- }
-
- return sw.toString();
- }
-
- static String buildThreadDump() {
- StringBuilder dump = new StringBuilder();
- Map<Thread, StackTraceElement[]> stackTraces = Thread.getAllStackTraces();
- for (Map.Entry<Thread, StackTraceElement[]> e : stackTraces.entrySet()) {
- Thread thread = e.getKey();
- dump.append(String.format(
- "\"%s\" %s prio=%d tid=%d %s\njava.lang.Thread.State: %s",
- thread.getName(),
- (thread.isDaemon() ? "daemon" : ""),
- thread.getPriority(),
- thread.getId(),
- Thread.State.WAITING.equals(thread.getState()) ?
- "in Object.wait()" : thread.getState().name().toLowerCase(Locale.ROOT),
- Thread.State.WAITING.equals(thread.getState()) ?
- "WAITING (on object monitor)" : thread.getState()));
- for (StackTraceElement stackTraceElement : e.getValue()) {
- dump.append("\n at ");
- dump.append(stackTraceElement);
- }
- dump.append("\n");
- }
- return dump.toString();
- }
-
- static String buildDeadlockInfo() {
- ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
- long[] threadIds = threadBean.findMonitorDeadlockedThreads();
- if (threadIds != null && threadIds.length > 0) {
- StringWriter stringWriter = new StringWriter();
- PrintWriter out = new PrintWriter(stringWriter);
-
- ThreadInfo[] infos = threadBean.getThreadInfo(threadIds, true, true);
- for (ThreadInfo ti : infos) {
- printThreadInfo(ti, out);
- printLockInfo(ti.getLockedSynchronizers(), out);
- out.println();
- }
-
- out.close();
- return stringWriter.toString();
- } else {
- return null;
- }
- }
-
- private static void printThreadInfo(ThreadInfo ti, PrintWriter out) {
- // print thread information
- printThread(ti, out);
-
- // print stack trace with locks
- StackTraceElement[] stacktrace = ti.getStackTrace();
- MonitorInfo[] monitors = ti.getLockedMonitors();
- for (int i = 0; i < stacktrace.length; i++) {
- StackTraceElement ste = stacktrace[i];
- out.println(INDENT + "at " + ste.toString());
- for (MonitorInfo mi : monitors) {
- if (mi.getLockedStackDepth() == i) {
- out.println(INDENT + " - locked " + mi);
- }
- }
- }
- out.println();
- }
-
- private static void printThread(ThreadInfo ti, PrintWriter out) {
- out.print("\"" + ti.getThreadName() + "\"" + " Id="
- + ti.getThreadId() + " in " + ti.getThreadState());
- if (ti.getLockName() != null) {
- out.print(" on lock=" + ti.getLockName());
- }
- if (ti.isSuspended()) {
- out.print(" (suspended)");
- }
- if (ti.isInNative()) {
- out.print(" (running in native)");
- }
- out.println();
- if (ti.getLockOwnerName() != null) {
- out.println(INDENT + " owned by " + ti.getLockOwnerName() + " Id="
- + ti.getLockOwnerId());
- }
- }
-
- private static void printLockInfo(LockInfo[] locks, PrintWriter out) {
- out.println(INDENT + "Locked synchronizers: count = " + locks.length);
- for (LockInfo li : locks) {
- out.println(INDENT + " - " + li);
- }
- out.println();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/hbase/blob/c2ee82c9/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index b23a966..1cb5082 100755
--- a/pom.xml
+++ b/pom.xml
@@ -677,7 +677,7 @@
<properties>
<property>
<name>listener</name>
- <value>org.apache.hadoop.hbase.HBaseClassTestRuleChecker,org.apache.hadoop.hbase.ResourceCheckerJUnitListener</value>
+ <value>org.apache.hadoop.hbase.TimedOutTestsListener,org.apache.hadoop.hbase.HBaseClassTestRuleChecker,org.apache.hadoop.hbase.ResourceCheckerJUnitListener</value>
</property>
</properties>
</configuration>