diff --git a/platform/testFramework/src/com/intellij/testFramework/ThreadTracker.java b/platform/testFramework/src/com/intellij/testFramework/ThreadTracker.java index 1a8fd1e81a42..b36d3f231bf2 100644 --- a/platform/testFramework/src/com/intellij/testFramework/ThreadTracker.java +++ b/platform/testFramework/src/com/intellij/testFramework/ThreadTracker.java @@ -38,6 +38,7 @@ import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; import java.util.Set; +import java.util.concurrent.ForkJoinWorkerThread; import java.util.concurrent.TimeUnit; /** @@ -151,6 +152,10 @@ public class ThreadTracker { continue; } + if (isIdleCommonPoolThread(thread, stackTrace)) { + continue; + } + @SuppressWarnings("NonConstantStringShouldBeStringBuffer") String trace = "Thread leaked: " + thread + "; " + thread.getState() + " (" + thread.isAlive() + ")\n--- its stacktrace:\n"; for (final StackTraceElement stackTraceElement : stackTrace) { @@ -171,7 +176,7 @@ public class ThreadTracker { } // true if somebody started new thread via "executeInPooledThread()" and then the thread is waiting for next task - private static boolean isIdleApplicationPoolThread(Thread thread, StackTraceElement[] stackTrace) { + private static boolean isIdleApplicationPoolThread(@NotNull Thread thread, @NotNull StackTraceElement[] stackTrace) { if (!isWellKnownOffender(thread)) return false; boolean insideTPEGetTask = Arrays.stream(stackTrace) .anyMatch(element -> element.getMethodName().equals("getTask") @@ -180,6 +185,16 @@ public class ThreadTracker { return insideTPEGetTask; } + private static boolean isIdleCommonPoolThread(@NotNull Thread thread, @NotNull StackTraceElement[] stackTrace) { + if (!ForkJoinWorkerThread.class.isAssignableFrom(thread.getClass())) { + return false; + } + boolean insideAwaitWork = Arrays.stream(stackTrace) + .anyMatch(element -> element.getMethodName().equals("awaitWork") + && element.getClassName().equals("java.util.concurrent.ForkJoinPool")); + return insideAwaitWork; + } + public static void awaitJDIThreadsTermination(int timeout, @NotNull TimeUnit unit) { awaitThreadTerminationWithParentParentGroup("JDI main", timeout, unit); }