Repository navigation
FileSystemInfo.Attributes set to -1 if the file gets deleted while in an enumeration on Unix #22033
Description
Summary
When a file gets deleted (or renamed) during an enumeration of all files in the parent directory, accessing the 'Attributes' property of the FileInfo object returns value '-1'. This seems very bad to me because it's not a meaningful FileAttributes value and thus the subsequent tests like (filesystemInfo.Attributes & FileAttributes.Hidden) != 0 will give unexpected results and cause problems.
There are 2 issues in my observation:
- Inconsistent behavior between Windows and Unix platforms.
- On Windows,
filesystemInfo.Attributesreturns the original attributes even though the file gets deleted during the enumeration.
- On Windows,
- Breaking change in behavior from
Microsoft.NetCore.App 2.0.0-preview1-002106-00toMicrosoft.NetCore.App 2.0.0-preview2-25324-03- With version
2.0.0-preview1-002106-00,filesystemInfo.Attributesraises anFileNotFoundExceptionexception. - With version
2.0.0-preview2-25324-03,filesystemInfo.Attributesreturns -1
- With version
Thought
I think it would be the best if we can have the consistent behavior between Windows and Unix platforms.
If that's technically not possible, then throwing FileNotFoundException exception is better than returnning -1 because -1 is not a meaningful value for FileAttributes and it will mislead the subsequent code.
Repro
Program.cs
using System;
using System.IO;
namespace test
{
class Program
{
static void Main(string[] args)
{
string testDir = Path.Combine(Environment.GetEnvironmentVariable("HOME"), "temp");
DirectoryInfo dir = new DirectoryInfo(testDir);
foreach (FileSystemInfo fileSystemInfo in dir.EnumerateFiles())
{
if (string.Equals(fileSystemInfo.Name, "bb.txt", StringComparison.InvariantCulture))
{
File.Delete(fileSystemInfo.FullName);
}
try {
Console.WriteLine("{0} - {1}", fileSystemInfo.Name, fileSystemInfo.Attributes);
} catch (System.IO.FileNotFoundException ex) {
Console.WriteLine("{0}: {1}", ex.GetType().FullName, ex.Message);
Console.WriteLine(ex.StackTrace);
}
}
}
}
}Result:
## Linux
## .NET Command Line Tools (2.0.0-preview1-005952)
## Microsoft .NET Core Shared Framework Host
## Version : 2.0.0-preview1-002106-00
## Build : 86fe9816c8ba782241c441c3228c665e393c3ef3
> dotnet run
cc.txt - Normal
System.IO.FileNotFoundException: Could not find file '/home/pi/temp/bb.txt'.
at System.IO.FileSystemInfo.EnsureStatInitialized()
at System.IO.FileSystemInfo.System.IO.IFileSystemObject.get_Attributes()
at System.IO.FileSystemInfo.get_Attributes()
at test.Program.Main(String[] args)
aa.txt - Normal
## Linux
## .NET Command Line Tools (2.0.0-preview2-006195)
## Microsoft .NET Core Shared Framework Host
## Version : 2.0.0-preview2-25324-03
## Build : b6c9f8ad69dc3edd601e288198de27975b514306
> dotnet run
bb.txt - -1
aa.txt - Normal
cc.txt - Normal
## Windows
## .NET Command Line Tools (2.0.0-preview2-006195)
## Microsoft .NET Core Shared Framework Host
## Version : 2.0.0-preview2-25324-03
## Build : b6c9f8ad69dc3edd601e288198de27975b514306
> dotnet run
aa.txt - Archive
bb.txt - Archive
cc.txt - Archive
Activity
danmoseley commentedon May 30, 2017
@JeremyKuhne please evaluate whether this needs to be in 2.0
JeremyKuhne commentedon May 31, 2017
The issue here is more around state refresh rather than "bad" behavior. If the file is missing in desktop (.NET FX) you get -1 if the state gets/needs refreshed. Desktop never throws on Attributes access. We should look at getting the "refresh" state in better alignment, but going back to throwing isn't a portable answer.
Fyi, I'm in the process of updating the documentation about this behavior.
JeremyKuhne commentedon May 31, 2017
Putting in 2.0 so we can look at what it takes to get the refresh state aligned.
danmoseley commentedon Jun 14, 2017
@JeremyKuhne I guess we can close this
daxian-dbw commentedon Jun 14, 2017
Thanks for the fix! Where can I find the documentation about this behavior on both Windows and Unix?
JeremyKuhne commentedon Jun 14, 2017
I've got a change in process to update the docs to describe the current behavior. dotnet/docs#2209 I've been busy getting the fixes through, I should hopefully get it finished shortly.