Cleanup NativeItemExists()#6929
Conversation
123c38a to
0b84586
Compare
|
Reopen to restart CIs. |
|
@TravisEz13 Could you please help - I can not find why CIs failed? |
|
Feature tests failed with Pester not found. 😕 |
There was a problem hiding this comment.
extra whitespace after equals sign
There was a problem hiding this comment.
perhaps use named parameter to make it more clear what unused is?
There was a problem hiding this comment.
unused here is self explaination - we don't use the parameter at all.
There was a problem hiding this comment.
Extra space fixed.
There was a problem hiding this comment.
Are we sure we no longer have a perf penalty with this change?
There was a problem hiding this comment.
We have still a perf penalty (on windows because normalization(!) - one extra kernel call in .Net code) but it is tracked in CoreFX https://github.com/dotnet/corefx/issues/19717
We have already mentioned that we do up to 7 the normalizations of the same path per cmdlet call. So perf penalty is more in PowerShell code. I'm trying to find how we can reduce the path normalization perf penalty.
Also please see https://github.com/dotnet/corefx/issues/27049#issuecomment-392826352 - .Net team is ready to help.
|
The Linux failure does not seem related to your change |
NativeItemExists -> ItemExists NativeFileExists -> FileExists NativeDirectoryExists -> DirectoryExists
8e8ac45 to
67c5d33
Compare
|
@TravisEz13 Thanks! But CIs failed again. I rebased - perhaps it resolve.. |
No need in throw here if file not found. (Previously we could throw in rare cases.)
|
@SteveL-MSFT @TravisEz13 Please review last two commits. I found my mistake. I added new comment and TODO to continue the cleanup process later. |
| exception = new UnauthorizedAccessException(win32Exception.Message, win32Exception); | ||
| } | ||
| else if (errorCode == 32) | ||
| { |
There was a problem hiding this comment.
File.GetAttributes doesn't spend this extra effort in case the errorCode is 32 (ERROR_SHARING_VIOLATION). So, this is potentially a breaking change.
There was a problem hiding this comment.
The same happens to WinSafeGetFileAttributes which is removed by #6909.
There was a problem hiding this comment.
Please see the PR description (Fix is ready in CoreFX, we get it in 2.1.1.)
There was a problem hiding this comment.
Please see the PR description - we'll get the fix in .Net Core 2.1.1.
There was a problem hiding this comment.
OK, so this will only affect c:\pagefile.sys? If so, then it's fine to leave it as is.
There was a problem hiding this comment.
Three files - pagefile.sys, hiberfil.sys, swapfile.sys. In the CoreFX PR a comment says that they can not emulate the behavior and so use the real file c:\pagefile.sys in test. I think users are unlikely to find something like this
| // Use 'File.GetAttributes()' because we want to get access exceptions. | ||
| // TODO: we should review the tricky logic | ||
| // (historically we throw 'UnauthorizedAccessException' here) and migrate | ||
| // to standard methods 'File.Exist()' and 'Directory.Exists()' where possible. |
There was a problem hiding this comment.
Why having this todo comment? File.GetAttributes will also throw UnauthorizedAccessException when the error is ERROR_ACCESS_DENIED.
And can you please point me to the places where it turns to File.Exists() and Directory.Exits() when NativeItemExists fails?
There was a problem hiding this comment.
Seems my comment is not clear.
I meant that we should migrate from the ItemExists method to File.Exists() and Directory.Exits() which don't throw UnauthorizedAccessException.
There was a problem hiding this comment.
Yeah, I agree. I also pointed that out in my comments. Open an issue to track that migration instead of this comment. This comment is not useful in the context of this method, which is designed to throw on error.
There was a problem hiding this comment.
TODO comment was removed.
| #else | ||
|
|
||
| #if !UNIX | ||
| if (IsReservedDeviceName(path)) |
There was a problem hiding this comment.
You don't need to enclose this in #if !Unix. The method body already separate the Unix/Windows code path.
There was a problem hiding this comment.
Seems method in line 898 (internal static bool ItemExists(string path)) is used on Unix.
There was a problem hiding this comment.
Take a look at the method IsReservedDeviceName, it's body already takes care of the #if/def.
There was a problem hiding this comment.
:-) I looked the other way.
Fixed.
| String filePath = stringBuilder.ToString(); | ||
|
|
||
| if (Utils.NativeFileExists(filePath)) | ||
| if (File.Exists(filePath)) |
There was a problem hiding this comment.
Why not use Utils.FileExists ?
There was a problem hiding this comment.
Utils.FileExists behavior is the same (no exception is thrown). So it is better to use the standard method.
There was a problem hiding this comment.
It's better to make all the Utils.NativeFileExists -> File/Directory.Exists changes in a separate PR. So for now, just do the simple replacement of Utils.NativeFileExists -> Utils.FileExists.
| { | ||
| string moduleFile = Path.Combine(directoryToCheck, proposedModuleName) + ext; | ||
| if (!Utils.NativeFileExists(moduleFile)) | ||
| if (!File.Exists(moduleFile)) |
There was a problem hiding this comment.
Same here.
Actually, I see Utils.NativeFileExists and File.Exists mixed in this file (possibly in that files too). Do we really care about the exception on failure in those cases?
There was a problem hiding this comment.
Utils.FileExists behavior is the same (no exception is thrown). So it is better to use the standard method.
Yes, we should review all these cases but there are dozens of them to do in this PR or in a new?
There was a problem hiding this comment.
Yeah. let's do it in a separate PR. For this PR, just do the simple rename replacement: Utils.NativeFileExists -> Utils.FileExists.
| if (accessException != null) | ||
| catch (Exception accessException) | ||
| { | ||
| ErrorRecord errorRecord = new ErrorRecord(accessException, "RemoveFileSystemItemUnAuthorizedAccess", ErrorCategory.PermissionDenied, directory); |
There was a problem hiding this comment.
Looks to me it's expecting an UnauthorizedAccessException, shall we narrow the catch to only catch this type of exception?
There was a problem hiding this comment.
Here I only preserve the logic.
Really we should clean up the code too because .Net Core support reparse points and recursion https://github.com/dotnet/corefx/blob/f25eb288a449010574a6e95fe298f3ad880ada1e/src/System.IO.FileSystem/src/System/IO/FileSystem.Windows.cs#L359
Seems we should clean up all code in FileSystemProvider - perhaps we don't need FileSystemProviderV2 :-)
There was a problem hiding this comment.
@daxian-dbw I opened #7017 to clean up the code.
There was a problem hiding this comment.
I'm fine leaving this catch as is.
| { | ||
| throw accessException; | ||
| } | ||
| result = Utils.ItemExists(path, out bool unused); |
| string sysRoot = System.Environment.GetEnvironmentVariable("SystemRoot"); | ||
| string urlmonPath = Path.Combine(sysRoot, @"System32\urlmon.dll"); | ||
| if (Utils.NativeFileExists(urlmonPath)) | ||
| if (Utils.FileExists(urlmonPath)) |
There was a problem hiding this comment.
At least for these two uses, they do not expect exception to be thrown. So change them to File.Exists should be fine.
There was a problem hiding this comment.
Maybe revert these two changes too, since we agreed to use a separate PR for the migration changes.
| // This is done through P/Invoke since we pay 13% performance degradation | ||
| // through the CAS checks required by File.Exists and Directory.Exists | ||
| internal static bool NativeDirectoryExists(string path) | ||
| internal static bool DirectoryExists(string path) |
There was a problem hiding this comment.
I think we should change the name of this one and FileExists to something that indicate it might throw exception, so it's easy to tell whether you should use them instead of File.Exists and Directory.Exists when writing code.
I suggest rename them to CheckFileExistsAndThrowOnError and CheckDirectoryExistsAndThrowOnError.
There was a problem hiding this comment.
I'll rename if we will not migrate to File.Exists/Directory.Exists in the PR.
There was a problem hiding this comment.
No, let's use a separate PR to do the migration changes. Go ahead rename this method.
| // This is done through P/Invoke since File.Exists and Directory.Exists pay 13% performance degradation | ||
| // through the CAS checks, and are terribly slow for network paths. | ||
| internal static bool NativeItemExists(string path, out bool isDirectory, out Exception exception) | ||
| internal static bool ItemExists(string path, out bool isDirectory) |
There was a problem hiding this comment.
Similarly, maybe changing this to CheckItemExistsAndThrowOnError.
There was a problem hiding this comment.
I'll rename if we will not migrate to File.Exists/Directory.Exists in the PR.
|
@daxian-dbw I am trying to keep the PR as small as possible. There are dozens of places where we should consider replacing old code (ItemExists) with File.Exists (Directory.Exists). Do you want I do it in this PR? |
|
@iSazonov No, you don't need to do it in this PR. Open an issue to track the analysis and migration work (Utils.FileExists/DirectoryExists => File.Exists/Directory.Exists). |
|
Tracking Issue #7031 |
|
@daxian-dbw File.Exists() and Directory.Exists() return false for device names so we can remove IsReservedDeviceName call from ItemExists() method at all. What do you think? |
|
@iSazonov |
|
The changes LGTM. |
No, I'll remove the methods in follow PR.
Never mind - I hope to remove ItemExists() altogether in follow PR. |
|
@daxian-dbw Should I fix something else? |
daxian-dbw
left a comment
There was a problem hiding this comment.
@iSazonov If you plan to remove those methods in your next PR, then it's fine to leave their names unchanged.
|
@daxian-dbw My thoughts was that if we have to re-publish psl-native after every change |

PR Summary
Related #6874. After the PR we can remove the files - isfile.cpp, isfile.h, isdirectory.cpp, isdirectory.h - from psl.
PR Checklist
.h,.cpp,.cs,.ps1and.psm1files have the correct copyright headerWIP:to the beginning of the title and remove the prefix when the PR is ready.[feature]if the change is significant or affects feature tests