Patch ThreadTracker during Kotlin plugin init
This commit is contained in:
@@ -95,9 +95,7 @@ fun doKotlinTearDown(project: Project, runnable: RunnableWithException) {
|
||||
|
||||
fun doKotlinTearDown(project: Project, runnable: () -> Unit) {
|
||||
unInvalidateBuiltinsAndStdLib(project) {
|
||||
patchThreadTracker {
|
||||
runnable()
|
||||
}
|
||||
runnable()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,55 +146,4 @@ fun Document.extractMarkerOffset(project: Project, caretMarker: String = "<caret
|
||||
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(this)
|
||||
|
||||
return offset
|
||||
}
|
||||
|
||||
private val patched = AtomicBoolean(false)
|
||||
|
||||
fun patchThreadTracker(runnable: RunnableWithException) {
|
||||
patchThreadTracker {
|
||||
runnable.run()
|
||||
}
|
||||
}
|
||||
|
||||
fun patchThreadTracker(runnable: () -> Unit) {
|
||||
fun patch() {
|
||||
if (patched.get()) return
|
||||
|
||||
patched.compareAndSet(false, true)
|
||||
|
||||
IdeaForkJoinWorkerThreadFactory.setupForkJoinCommonPool()
|
||||
|
||||
// Check setup was successful
|
||||
val commonPoolFactoryName = ForkJoinPool.commonPool().factory.javaClass.name
|
||||
if (commonPoolFactoryName == IdeaForkJoinWorkerThreadFactory::class.java.name) {
|
||||
return
|
||||
}
|
||||
|
||||
println("Patching!")
|
||||
|
||||
try {
|
||||
val wellKnownOffendersField = try {
|
||||
ThreadTracker::class.java.getDeclaredField("wellKnownOffenders")
|
||||
}
|
||||
catch (communityPropertyNotFoundEx: NoSuchFieldException) {
|
||||
ThreadTracker::class.java.getDeclaredField("a")
|
||||
}
|
||||
|
||||
wellKnownOffendersField.isAccessible = true
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val wellKnownOffenders = wellKnownOffendersField.get(null) as MutableSet<String>
|
||||
|
||||
wellKnownOffenders.add("ForkJoinPool.commonPool-worker-")
|
||||
}
|
||||
catch (e: NoSuchFieldException) {
|
||||
println("Patching failed: " + e)
|
||||
}
|
||||
catch (e: IllegalAccessException) {
|
||||
println("Patching failed: " + e)
|
||||
}
|
||||
}
|
||||
|
||||
patch()
|
||||
runnable()
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed 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.jetbrains.kotlin.idea
|
||||
|
||||
import com.intellij.concurrency.IdeaForkJoinWorkerThreadFactory
|
||||
import com.intellij.testFramework.ThreadTracker
|
||||
import java.util.concurrent.ForkJoinPool
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
/*
|
||||
Workaround for ThreadTracker.checkLeak() failures on TeamCity.
|
||||
|
||||
Currently TeamCity runs tests in classloader without boot.jar where IdeaForkJoinWorkerThreadFactory is defined. That
|
||||
makes ForkJoinPool.commonPool() silently ignores java.util.concurrent.ForkJoinPool.common.threadFactory
|
||||
(because of java.lang.ClassNotFoundException) option during factory initialization.
|
||||
|
||||
Standard names for ForkJoinPool threads doesn't pass ThreadTracker.checkLeak() check and that ruins tests constantly.
|
||||
As it's allowed to reorder tests on TeamCity and any test can be first at some point, this patch should be applied at
|
||||
some common place.
|
||||
*/
|
||||
object ForkJoinPoolPatcherForTeamCityTesting {
|
||||
private val patched = AtomicBoolean(false)
|
||||
|
||||
fun patchThreadTracker() {
|
||||
if (patched.get()) return
|
||||
|
||||
patched.compareAndSet(false, true)
|
||||
|
||||
IdeaForkJoinWorkerThreadFactory.setupForkJoinCommonPool()
|
||||
|
||||
// Check setup was successful and patching isn't needed
|
||||
val commonPoolFactoryName = ForkJoinPool.commonPool().factory.javaClass.name
|
||||
if (commonPoolFactoryName == IdeaForkJoinWorkerThreadFactory::class.java.name) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
val wellKnownOffendersField = try {
|
||||
ThreadTracker::class.java.getDeclaredField("wellKnownOffenders")
|
||||
}
|
||||
catch (communityPropertyNotFoundEx: NoSuchFieldException) {
|
||||
ThreadTracker::class.java.getDeclaredField("a")
|
||||
}
|
||||
|
||||
wellKnownOffendersField.isAccessible = true
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val wellKnownOffenders = wellKnownOffendersField.get(null) as MutableSet<String>
|
||||
|
||||
wellKnownOffenders.add("ForkJoinPool.commonPool-worker-")
|
||||
println("Patching ThreadTracker was successful")
|
||||
}
|
||||
catch (e: NoSuchFieldException) {
|
||||
println("Patching ThreadTracker failed: " + e)
|
||||
}
|
||||
catch (e: IllegalAccessException) {
|
||||
println("Patching ThreadTracker failed: " + e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,10 @@ public class PluginStartupComponent implements ApplicationComponent {
|
||||
public void initComponent() {
|
||||
registerPathVariable();
|
||||
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
ForkJoinPoolPatcherForTeamCityTesting.INSTANCE.patchThreadTracker();
|
||||
}
|
||||
|
||||
JarUserDataManager.INSTANCE.register(KotlinJavaScriptLibraryDetectionUtil.HasKotlinJSMetadataInJar.INSTANCE);
|
||||
|
||||
DebuggerFiltersUtilKt.addKotlinStdlibDebugFilterIfNeeded();
|
||||
|
||||
@@ -18,8 +18,6 @@ package org.jetbrains.kotlin.idea;
|
||||
|
||||
import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase;
|
||||
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
|
||||
import org.jetbrains.kotlin.idea.test.RunnableWithException;
|
||||
import org.jetbrains.kotlin.idea.test.TestUtilsKt;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
|
||||
abstract public class KotlinDaemonAnalyzerTestCase extends DaemonAnalyzerTestCase {
|
||||
@@ -31,12 +29,7 @@ abstract public class KotlinDaemonAnalyzerTestCase extends DaemonAnalyzerTestCas
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
TestUtilsKt.patchThreadTracker(new RunnableWithException() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
KotlinDaemonAnalyzerTestCase.super.tearDown();
|
||||
}
|
||||
});
|
||||
super.tearDown();
|
||||
VfsRootAccess.disallowRootAccess(KotlinTestUtils.getHomeDirectory());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,8 +45,6 @@ import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade;
|
||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime;
|
||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil;
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase;
|
||||
import org.jetbrains.kotlin.idea.test.RunnableWithException;
|
||||
import org.jetbrains.kotlin.idea.test.TestUtilsKt;
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
@@ -101,7 +99,6 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
|
||||
ConfigLibraryUtil.addLibrary(customLibEditor, model);
|
||||
}
|
||||
|
||||
@SuppressWarnings("MethodDoesntCallSuperMethod")
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
if (getTestName(true).startsWith("dex")) {
|
||||
@@ -116,12 +113,7 @@ public abstract class KotlinDebuggerTestCase extends DescriptorTestCase {
|
||||
}
|
||||
});
|
||||
|
||||
TestUtilsKt.patchThreadTracker(new RunnableWithException() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
KotlinDebuggerTestCase.super.tearDown();
|
||||
}
|
||||
});
|
||||
super.tearDown();
|
||||
VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory());
|
||||
}
|
||||
|
||||
|
||||
@@ -17,15 +17,8 @@
|
||||
package org.jetbrains.kotlin.idea.rename
|
||||
|
||||
import org.jetbrains.kotlin.idea.refactoring.rename.AbstractRenameTest
|
||||
import org.jetbrains.kotlin.idea.test.patchThreadTracker
|
||||
import org.jetbrains.kotlin.tests.ULTIMATE_TEST_DATA_DIR
|
||||
|
||||
abstract class AbstractUltimateRenameTest : AbstractRenameTest() {
|
||||
override fun getTestDataPath() = ULTIMATE_TEST_DATA_DIR
|
||||
|
||||
override fun tearDown() {
|
||||
patchThreadTracker {
|
||||
super.tearDown()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user