From 9a423e593128621884054e6869dcec145ed401ce Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 14 Jul 2017 19:24:47 +0300 Subject: [PATCH] avoid attach listener/write action race which could lead to unresponsiveness When we try to attach app listener in the unfortunate moment between application firing beforeWriteActionStart() and actual write action start, all attached listeners won't be fired during this write action. To avoid that, we check that if after attaching listener the app is still trying to start write action, then we declare the moment unfortunate, detach listener and try again. --- .../ex/GlobalInspectionContextImpl.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java index a715a7c0dcaa..ad31057240bd 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java @@ -451,10 +451,17 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp while (true) { Disposable disposable = Disposer.newDisposable(); ProgressIndicator wrapper = new SensitiveProgressWrapper(progressIndicator); - wrapper.start(); - ProgressIndicatorUtils.forceWriteActionPriority(wrapper, disposable); try { + // avoid "attach listener"/"write action" race + ReadAction.run(() -> { + wrapper.start(); + ProgressIndicatorUtils.forceWriteActionPriority(wrapper, disposable); + // there is a chance we are racing with write action, in which case just registered listener might not be called, retry. + if (ApplicationManagerEx.getApplicationEx().isWriteActionPending()) { + throw new ProcessCanceledException(); + } + }); // use wrapper here to cancel early when write action start but do not affect the original indicator ((JobLauncherImpl)JobLauncher.getInstance()).processQueue(filesToInspect, filesFailedToInspect, wrapper, TOMBSTONE, processor); break;