From 264496f7ce93370df0f0b9d2f89f40b73c7bf63f Mon Sep 17 00:00:00 2001 From: Ruslan Cheremin Date: Sun, 28 Jun 2026 21:52:27 +0200 Subject: [PATCH] [vfs] IJPL-248377: check directory is valid before resolving child + Doesn't fix the issue completely but reduces it's frequency (cherry picked from commit 9e7223e16153e3a84f4e4b076d390cc150c0bd78) IJ-CR-211437 GitOrigin-RevId: 9040dd2e46e387f886697ea7ae5d8e1cff979c32 --- .../vfs/newvfs/impl/VirtualDirectoryImpl.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java index 15159a8cc4fe..b2430f6bd8c2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java @@ -231,6 +231,14 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { boolean isCaseSensitive) { VirtualFileSystemEntry newlyLoadedChild; synchronized (directoryData) { + VfsData vfsData = getVfsData(); + if (!vfsData.isFileValid(getId()) ) { + //Accessing !valid file must be filtered above, but some VFS ops are still executed outside RA/WA framework + // => vfile could be deleted concurrently => re-check it here, before potentially doing something unnatural + // to dead file's .children: + return null; + } + // usually we come here after unsuccessful findInCachedChildren() -- but maybe another findChild() sneaked in the middle? VirtualFileSystemEntry existingChild = findInCachedChildren(name, isCaseSensitive); if (existingChild != null) return existingChild; // including NULL_VIRTUAL_FILE @@ -238,7 +246,6 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { return null;//all children loaded, but child not found -> not exist } - VfsData vfsData = getVfsData(); PersistentFSImpl pFS = vfsData.owningPersistentFS(); ChildInfo childInfo = pFS.findChildInfo(this, name, fileSystem); if (childInfo == null) { @@ -905,6 +912,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { String childName = child.getName(); synchronized (directoryData) { + //MAYBE RC: check directory is not yet invalidated (.isValid())? directoryData.removeAdoptedName(childName); VfsData.ChildrenIds children = directoryData.children; @@ -1082,6 +1090,9 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { @Override public void invalidate(@NotNull Object source, @NotNull Object reason) { super.invalidate(source, reason); + //MAYBE RC: how to protect from modifying already invalidated file: + // create a new INVALIDATED flag, and ChildrenIds.INVALIDATED_CHILDREN=ChildrenIds(empty,INVALIDATED) + // check the flag in each ChildrenIds modification methods? directoryData.children = VfsData.ChildrenIds.EMPTY; } @@ -1199,7 +1210,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { if (PersistentFSRecordAccessor.hasDeletedFlag(childAttributes)) { //It is an error to come here with childId which was already deleted -- such childId should be removed from ChildrenIds // list first, see PersistentFSImpl.executeDelete() - throw new FileDeletedException(childId, "file is deleted, but still in [" + getId() + "].children list."); + throw new FileDeletedException(childId, "file is deleted, but still in [" + getId() + "].children list " + directoryData.children); } int childNameId = vfsPeer.getNameIdByFileId(childId);