2/2 Make SwallowingNotificationListener thread-safe

SwallowingNotificationListener is access from different Gradle thread
pool threads.

You can reproduce it by running
`ProjectTemplateNewWizardProjectImportTestGenerated.GradleKts.testComposeMultiplatformApplication`
and checking from which threads the same instance of
SwallowingNotificationListener is accessed.

This commit is an attempt to fight against the
`testComposeMultiplatformApplication` test flakiness.

The previous commit to fight agains the test flakiness isn't enough
because there two types of threads from which
SwallowingNotificationListener is accessed. One type of the access you
can see in the stacktrace in the commit message of the previous commit.

The other type is from Gradle "Connection worker" thread:

  java.lang.StringIndexOutOfBoundsException: begin 1, end 123, length 1
    at java.base/java.lang.String.checkBoundsBeginEnd(String.java:4604)
    at java.base/java.lang.String.substring(String.java:2707)
    at com.intellij.execution.process.AnsiStreamingLexer.getElementText(AnsiStreamingLexer.java:50)
    at com.intellij.execution.process.AnsiStreamingLexer.getElementTextSmart(AnsiStreamingLexer.java:62)
    at com.intellij.execution.process.AnsiEscapeDecoder.escapeText(AnsiEscapeDecoder.java:54)
    at com.intellij.openapi.externalSystem.service.execution.ExternalSystemProcessHandler.notifyTextAvailable(ExternalSystemProcessHandler.java:65)
    at com.intellij.openapi.externalSystem.util.ExternalSystemUtil$2$3.onTaskOutput(ExternalSystemUtil.java:442)
    at com.intellij.openapi.externalSystem.service.remote.ExternalSystemProgressNotificationManagerImpl$TaskListenerWrapper.onTaskOutput(ExternalSystemProgressNotificationManagerImpl.kt:111)
    at jdk.internal.reflect.GeneratedMethodAccessor955.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at com.intellij.util.EventDispatcher.dispatchVoidMethod(EventDispatcher.java:120)
    at com.intellij.util.EventDispatcher.lambda$createMulticaster$1(EventDispatcher.java:85)
    at jdk.proxy2/jdk.proxy2.$Proxy232.onTaskOutput(Unknown Source)
    at com.intellij.openapi.externalSystem.service.remote.ExternalSystemProgressNotificationManagerImpl$onTaskOutput$1.invoke(ExternalSystemProgressNotificationManagerImpl.kt:47)
    at com.intellij.openapi.externalSystem.service.remote.ExternalSystemProgressNotificationManagerImpl$onTaskOutput$1.invoke(ExternalSystemProgressNotificationManagerImpl.kt:47)
    at com.intellij.openapi.externalSystem.service.remote.ExternalSystemProgressNotificationManagerImpl.forEachListener(ExternalSystemProgressNotificationManagerImpl.kt:90)
    at com.intellij.openapi.externalSystem.service.remote.ExternalSystemProgressNotificationManagerImpl.onTaskOutput(ExternalSystemProgressNotificationManagerImpl.kt:47)
    at com.intellij.openapi.externalSystem.service.AbstractExternalSystemFacadeImpl$SwallowingNotificationListener.onTaskOutput(AbstractExternalSystemFacadeImpl.java:240)
    at org.jetbrains.plugins.gradle.service.execution.GradleProgressListener.sendProgressToOutputIfNeeded(GradleProgressListener.java:249)
    at org.jetbrains.plugins.gradle.service.execution.GradleProgressListener.statusChanged(GradleProgressListener.java:74)
    at jdk.internal.reflect.GeneratedMethodAccessor956.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)

As you can see it comes from statusChanged callback and it's not even
technically a Gradle output parsing.

IJ-MR-26323

GitOrigin-RevId: 8eb13df5a5d641d28634477f3dbf720cab53d303
This commit is contained in:
Nikita Bobko
2022-06-24 18:52:02 +02:00
committed by intellij-monorepo-bot
parent bb9a58b3ae
commit 72cbb44df6

View File

@@ -217,15 +217,15 @@ public abstract class AbstractExternalSystemFacadeImpl<S extends ExternalSystemE
}
@Override
public void onStart(@NotNull ExternalSystemTaskId id, String workingDir) {
public synchronized void onStart(@NotNull ExternalSystemTaskId id, String workingDir) {
}
@Override
public void onStart(@NotNull ExternalSystemTaskId id) {
public synchronized void onStart(@NotNull ExternalSystemTaskId id) {
}
@Override
public void onStatusChange(@NotNull ExternalSystemTaskNotificationEvent event) {
public synchronized void onStatusChange(@NotNull ExternalSystemTaskNotificationEvent event) {
try {
myManager.onStatusChange(event);
}
@@ -235,7 +235,7 @@ public abstract class AbstractExternalSystemFacadeImpl<S extends ExternalSystemE
}
@Override
public void onTaskOutput(@NotNull ExternalSystemTaskId id, @NotNull String text, boolean stdOut) {
public synchronized void onTaskOutput(@NotNull ExternalSystemTaskId id, @NotNull String text, boolean stdOut) {
try {
myManager.onTaskOutput(id, text, stdOut);
}
@@ -245,23 +245,23 @@ public abstract class AbstractExternalSystemFacadeImpl<S extends ExternalSystemE
}
@Override
public void onEnd(@NotNull ExternalSystemTaskId id) {
public synchronized void onEnd(@NotNull ExternalSystemTaskId id) {
}
@Override
public void onSuccess(@NotNull ExternalSystemTaskId id) {
public synchronized void onSuccess(@NotNull ExternalSystemTaskId id) {
}
@Override
public void onFailure(@NotNull ExternalSystemTaskId id, @NotNull Exception ex) {
public synchronized void onFailure(@NotNull ExternalSystemTaskId id, @NotNull Exception ex) {
}
@Override
public void beforeCancel(@NotNull ExternalSystemTaskId id) {
public synchronized void beforeCancel(@NotNull ExternalSystemTaskId id) {
}
@Override
public void onCancel(@NotNull ExternalSystemTaskId id) {
public synchronized void onCancel(@NotNull ExternalSystemTaskId id) {
}
}
}