Skip to content

Fix FileNotFoundEx crash when Fold happens on untitled: scheme doc #839

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 8, 2019

Conversation

rkeithhill
Copy link
Contributor

Fix PowerShell/vscode-powershell#1676

One change here that makes me a bit nervous is the added IsPathInMemory() test to the GetFile() method. However, I observed GetFile() crashing when it was passed an untitled: path as part of the repro for vscode 1676:

    System.AggregateException: One or more errors occurred. (Could not find file 'C:\Users\Keith\GitHub\PowerShell\Plaster\untitled:Untitled-2'.) ---> System.IO.FileNotFoundException: Could not find file 'C:\Users\Keith\GitHub\PowerShell\Plaster\untitled:Untitled-2'.
       at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
       at System.IO.FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
       at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
       at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access)
       at Microsoft.PowerShell.EditorServices.Workspace.GetFile(String filePath) in C:\Users\Keith\GitHub\rkeithhill\PowerShellEditorServices\src\PowerShellEditorServices\Workspace\Workspace.cs:line 118

So it seems prudent to ensure we never try to create a FileStream given an in-memory document uri. However, the IsPathInMemory() method utilizes exceptions in some cases to determine if the path is in-memory. That is why I put it second in the short-circuiting &&. So we would only do this test at the point we would actually try to open the file.

Another option would be to do the try/catch FileNotFoundEx in this method and then we could skip the IsPathInMemory() test. Thoughts?

Copy link
Contributor

@glennsarti glennsarti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Collaborator

@SeeminglyScience SeeminglyScience left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! :)

Another option would be to do the try/catch FileNotFoundEx in this method and then we could skip the IsPathInMemory() test. Thoughts?

I think it makes sense where you have it. As you said we should never try to create a file stream for in memory files, so adding that protection makes sense to me. I'd like to see IsPathInMemory changed to use a mix of Path.IsPathFullyQualified and Uri.TryCreate to make the call a little cheaper, but it's probably not a huge difference.

// Perhaps a better option would be to parse the contents of the document as a string
// as opposed to reading a file but the senario of "no backing file" probably doesn't
// warrant the extra effort.
ScriptFile scriptFile = editorSession.Workspace.GetFile(documentUri);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recently added a TryGetFile function that would do the soft check:

public bool TryGetFile(string filePath, out ScriptFile scriptFile)

maybe that's better to use here?

Copy link
Contributor Author

@rkeithhill rkeithhill Jan 2, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could (perhaps should) change the call site but there are 23 references to GetFile() so maybe we should still try to make GetFile() a little more robust? Either that OR we nuke make GetFile() private and replace all 23 references with calls to TryGetFile(). Longer term, that may be the better strategy because it makes it clearer you may not get a file back. GetFile() behaves similarly except that it returns a null when there is no file to return - which is way less obvious and easier to ignore the null case - kind of like ignoring error return codes in C code. :-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I don't think GetFile() handle's File exceptions:

using (FileStream fileStream = new FileStream(resolvedFilePath, FileMode.Open, FileAccess.Read))
using (StreamReader streamReader = new StreamReader(fileStream, Encoding.UTF8))

If FileStream or StreamReader throws an exception, that will bubble up I'm pretty sure, no?

Where as TryGetFile actually does catch them.

I think we should eventually move to using TryGetFile everywhere it makes sense... but we can call that out of scope for this PR if you'd like.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make the change to use TryGetFile() later tonight. Getting ready to head out to see Aquaman right now. :-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have a great time! I want to hear the full @rkeithhill review 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, updated to use TryGetFile() instead - reverted change to GetFile(). Although I did an "important" note on GetFile() that shows up in Intellisense that recommends TryGetFile() instead. Also, fix an incorrect (copy/paste) log message.

P.S. Aquaman was pretty good. Not as good as Wonder Woman IMO but way better than Dawn of Pustice. Then again, I've been a Jason Momoa fan since Stargate Atlantis. :-)

Copy link
Member

@TylerLeonhardt TylerLeonhardt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM :) potential nit in comments

@TylerLeonhardt TylerLeonhardt merged commit 3697d36 into master Jan 8, 2019
@TylerLeonhardt TylerLeonhardt deleted the rkeithhill/fix-vscode-1676-fold-untitled branch January 8, 2019 03:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants