How to avoid a race condition when a file is being opened in the Editor (Intellij)
Hi,
I am trying to solve what appears to be a race condition where FileEditorManagerOpenFileListener#fileOpened is called, the listener closes the file that was just opened using FileEditorManager#closeFile, which results in an exception com.intellij.openapi.util.TraceableDisposable$DisposalException: Editor is already disposed
Background: I am writing a plugin that will allow students to use intellij as a test platform for programming tests. The plugin monitors for disallowed files being opened during the test (using the above listener). When a disallowed file is opened, the file is closed by the listener and the student is notified.
Occasionally, the following exception results when the file is closed:
2024-11-21 15:41:32,283 [ 59227] SEVERE - #c.i.i.p.PluginManager - Editor is already disposed
com.intellij.openapi.util.TraceableDisposable$DisposalException: Editor is already disposed
at com.intellij.openapi.util.TraceableDisposable.throwDisposalError(TraceableDisposable.java:44)
at com.intellij.openapi.editor.impl.EditorImpl.throwDisposalError(EditorImpl.java:1020)
at com.intellij.openapi.editor.impl.view.LogicalPositionCache.checkDisposed(LogicalPositionCache.java:193)
at com.intellij.openapi.editor.impl.view.LogicalPositionCache.getLineInfo(LogicalPositionCache.java:178)
at com.intellij.openapi.editor.impl.view.LogicalPositionCache.offsetToLogicalPosition(LogicalPositionCache.java:90)
at com.intellij.openapi.editor.impl.view.EditorCoordinateMapper.offsetToLogicalPosition(EditorCoordinateMapper.java:91)
at com.intellij.openapi.editor.impl.view.EditorView.offsetToLogicalPosition(EditorView.java:172)
at com.intellij.openapi.editor.impl.EditorImpl.lambda$offsetToLogicalPosition$21(EditorImpl.java:1494)
at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:923)
at com.intellij.openapi.application.ReadAction.compute(ReadAction.java:76)
at com.intellij.openapi.editor.impl.EditorImpl.offsetToLogicalPosition(EditorImpl.java:1494)
at com.intellij.openapi.editor.impl.CaretImpl.lambda$moveToOffset$0(CaretImpl.java:106)
at com.intellij.openapi.editor.impl.CaretModelImpl.doWithCaretMerging(CaretModelImpl.java:419)
at com.intellij.openapi.editor.impl.CaretImpl.moveToOffset(CaretImpl.java:105)
at com.intellij.openapi.editor.CaretModel.moveToOffset(CaretModel.java:91)
at com.intellij.openapi.editor.CaretModel.moveToOffset(CaretModel.java:77)
at com.intellij.openapi.fileEditor.OpenFileDescriptor.navigateInEditor(OpenFileDescriptor.java:114)
at com.intellij.openapi.fileEditor.OpenFileDescriptor.navigateIn(OpenFileDescriptor.java:97)
at com.intellij.openapi.fileEditor.impl.text.TextEditorImpl.navigateTo(TextEditorImpl.kt:173)
at com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl.navigateAndSelectEditor(FileEditorManagerImpl.kt:1321)
at com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl.openEditorImpl(FileEditorManagerImpl.kt:1310)
at com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl.openFileEditor(FileEditorManagerImpl.kt:1258)
at com.intellij.openapi.fileEditor.FileNavigatorImplKt.navigateInAnyFileEditor(FileNavigatorImpl.kt:109)
at com.intellij.openapi.fileEditor.FileNavigatorImplKt.access$navigateInAnyFileEditor(FileNavigatorImpl.kt:1)
at com.intellij.openapi.fileEditor.FileNavigatorImpl.navigateInEditor(FileNavigatorImpl.kt:57)
at com.intellij.openapi.fileEditor.FileNavigatorImpl.navigateInEditorOrNativeApp(FileNavigatorImpl.kt:52)
at com.intellij.openapi.fileEditor.FileNavigatorImpl.navigate(FileNavigatorImpl.kt:32)
at com.intellij.openapi.fileEditor.OpenFileDescriptor.navigate(OpenFileDescriptor.java:88)
at com.intellij.platform.ide.navigation.impl.IdeNavigationServiceKt$navigateToSource$4$1.invoke(IdeNavigationService.kt:171)
at com.intellij.platform.ide.navigation.impl.IdeNavigationServiceKt$navigateToSource$4$1.invoke(IdeNavigationService.kt:170)
at com.intellij.openapi.progress.CoroutinesKt.blockingContext(coroutines.kt:248)
at com.intellij.openapi.progress.CoroutinesKt.blockingContext(coroutines.kt:199)
at com.intellij.platform.ide.navigation.impl.IdeNavigationServiceKt$navigateToSource$4.invokeSuspend(IdeNavigationService.kt:170)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at com.intellij.openapi.application.impl.DispatchedRunnable.run(DispatchedRunnable.kt:43)
at com.intellij.openapi.application.TransactionGuardImpl.runWithWritingAllowed(TransactionGuardImpl.java:208)
at com.intellij.openapi.application.TransactionGuardImpl.access$100(TransactionGuardImpl.java:21)
at com.intellij.openapi.application.TransactionGuardImpl$1.run(TransactionGuardImpl.java:190)
at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:861)
at com.intellij.openapi.application.impl.ApplicationImpl$4.run(ApplicationImpl.java:478)
at com.intellij.openapi.application.impl.FlushQueue.doRun(FlushQueue.java:79)
at com.intellij.openapi.application.impl.FlushQueue.runNextEvent(FlushQueue.java:121)
at com.intellij.openapi.application.impl.FlushQueue.flushNow(FlushQueue.java:41)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:792)
at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:739)
at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:733)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:761)
at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.kt:690)
at com.intellij.ide.IdeEventQueue._dispatchEvent$lambda$10(IdeEventQueue.kt:593)
at com.intellij.openapi.application.impl.ApplicationImpl.runWithoutImplicitRead(ApplicationImpl.java:1485)
at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.kt:593)
at com.intellij.ide.IdeEventQueue.access$_dispatchEvent(IdeEventQueue.kt:67)
at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:369)
at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:368)
at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:787)
at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:368)
at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:363)
at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$1(IdeEventQueue.kt:997)
at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:113)
at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:997)
at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$7(IdeEventQueue.kt:363)
at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:861)
at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.kt:405)
at com.intellij.openapi.progress.impl.PlatformTaskSupportKt.pumpEventsForHierarchy(PlatformTaskSupport.kt:379)
at com.intellij.openapi.progress.impl.PlatformTaskSupportKt.access$pumpEventsForHierarchy(PlatformTaskSupport.kt:1)
at com.intellij.openapi.progress.impl.PlatformTaskSupport$runWithModalProgressBlockingInternal$2.invoke(PlatformTaskSupport.kt:157)
at com.intellij.openapi.progress.impl.PlatformTaskSupport$runWithModalProgressBlockingInternal$2.invoke(PlatformTaskSupport.kt:135)
at com.intellij.openapi.application.impl.ModalityKt.inModalContext(modality.kt:12)
at com.intellij.openapi.progress.impl.PlatformTaskSupport.runWithModalProgressBlockingInternal(PlatformTaskSupport.kt:135)
at com.intellij.openapi.progress.impl.PlatformTaskSupport.access$runWithModalProgressBlockingInternal(PlatformTaskSupport.kt:41)
at com.intellij.openapi.progress.impl.PlatformTaskSupport$runWithModalProgressBlockingInternal$1.invoke(PlatformTaskSupport.kt:123)
at com.intellij.openapi.progress.impl.PlatformTaskSupport$runWithModalProgressBlockingInternal$1.invoke(PlatformTaskSupport.kt:119)
at com.intellij.openapi.progress.ContextKt.prepareThreadContext(context.kt:94)
at com.intellij.openapi.progress.impl.PlatformTaskSupport.runWithModalProgressBlockingInternal(PlatformTaskSupport.kt:119)
at com.intellij.openapi.progress.TasksKt.runWithModalProgressBlocking(tasks.kt:167)
at com.intellij.openapi.progress.TasksKt.runWithModalProgressBlocking(tasks.kt:99)
at com.intellij.util.OpenSourceUtilKt.openSourcesFrom(OpenSourceUtil.kt:24)
at com.intellij.util.OpenSourceUtil.openSourcesFrom(OpenSourceUtil.java:22)
at com.intellij.util.EditSourceOnDoubleClickHandler$TreeMouseListener.processDoubleClick(EditSourceOnDoubleClickHandler.kt:188)
at com.intellij.util.EditSourceOnDoubleClickHandler$TreeMouseListener.onDoubleClick(EditSourceOnDoubleClickHandler.kt:176)
at com.intellij.ui.DoubleClickListener.onClick(DoubleClickListener.java:30)
at com.intellij.ui.ClickListener$1.mouseReleased(ClickListener.java:58)
at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:298)
at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:297)
at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:297)
at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:297)
at java.desktop/java.awt.Component.processMouseEvent(Component.java:6657)
at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3385)
at com.intellij.ui.treeStructure.Tree.processMouseEvent(Tree.java:437)Diagnosis (guess): I suspect that there is a race condition between my listener and another thread which calls FileEditorManagerListener#fileOpenedSync(FileEditorManager, VirtualFile, List). Essentially, my listener closes the file while the other thread is still working on it.
Question 1: Is this the problem or is it another problem?
Question 2: If this is the problem, how can I avoid the race condition? I.e., perhaps by waiting until the other thread completes before the window is closed?
Thank you for your time.
Sincerely,
Alex
请先登录再写评论。
Hi,
Try scheduling closing files with
com.intellij.openapi.fileEditor.FileEditorManager#runWhenLoaded.Hi Karol,
Thanks! That seemed to fix the problem. I did need to wrap the call to FileEditorManager#closeFile with a ApplicationManager#invokeLater to make it work.
Thanks for your help!
Sincerely,
Alex