This is an archive of the discontinued LLVM Phabricator instance.

clang-format: Don't leave behind temp files in -i mode on Windows, PR26125, reloaded
ClosedPublic

Authored by thakis on Feb 26 2017, 4:56 PM.

Details

Reviewers
rnk
Summary

Second attempt after http://llvm.org/viewvc/llvm-project?rev=296166&view=rev

In the first attempt, Code (the memory buffer backing the input file) was reset before overwriteChangedFiles() was called, but overwriteChangedFiles() still reads from it.
This time, load the whole input file into memory instead of using mmap when formatting in-place.

(Since the test is identical to what was in the repo before chapuni's revert, svn diff doesn't show it – see the above link for the test.)

Diff Detail

Event Timeline

thakis created this revision.Feb 26 2017, 4:56 PM
klimek added inline comments.Feb 27 2017, 2:03 AM
include/clang/Rewrite/Core/Rewriter.h
188–197 ↗(On Diff #89823)

llvm.org seems to be down, so I cannot access the original patch - but I'm somewhat opposed to making this interface more complex. If we have a coupling of MemoryBuffer to the Rewriter, can we make that explicit instead?

thakis added inline comments.Feb 27 2017, 6:47 AM
include/clang/Rewrite/Core/Rewriter.h
188–197 ↗(On Diff #89823)

I think this generally requires per-app knowledge on when and how it's safe to free up memory buffers (for example, the fixit rewriter can't easily drop its inputs currently as far as I can tell without further refactorings). If you have a good suggestion, I'm all ears, but this seems like a fairly minor change that attempts to fix a fairly major bug. So if there's some better way of factoring this that I currently don't see, it's almost no work to move to that then.

Can we open the files with FILE_SHARE_DELETE instead?

Also, do we want to not call ReplaceFile in Path.inc on Win if it potentially leaves temp files lying around?
Reading the code, it looks like we currently actually believe it may fail, and retry with MoveFileEx afterwards...

rnk edited edge metadata.Feb 27 2017, 10:50 AM

My understanding is that Windows doesn't allow you to delete a file that has been opened and mapped into any process, even if it has been opened with FILE_SHARE_DELETE. One way to work around this would be to avoid memory mapping files in the SourceManager when using the Rewriter. Then FILE_SHARE_DELETE will do what you want. There should be a parameter to MemoryBuffer::getFile to control this. However, I think it really would be cleaner if we unmapped all of our MemoryBuffers of inputs before overwriting them in place. Keeping those buffers around feels like having dangling references.

amccarth added inline comments.
lib/Rewrite/Rewriter.cpp
455 ↗(On Diff #89823)

I'm not familiar with the structure of this code, but it seems odd to me that the callback is called prewrite when it happens _after_ the write.

thakis updated this revision to Diff 89923.Feb 27 2017, 1:20 PM
thakis edited the summary of this revision. (Show Details)

Here's a simpler fix, suggested by rnk.

thakis added inline comments.Feb 27 2017, 1:22 PM
lib/Rewrite/Rewriter.cpp
455 ↗(On Diff #89823)

obsolete now, but while it's true that it's called after the write to the temp file, it's called before the temp file is moved to the final location -- and for the client code of this function, the temp file is an implementation detail it doesn't know about, so it's really called before "the" write.

rnk accepted this revision.Feb 27 2017, 2:20 PM

lgtm

We should file a bug against the Rewriter interface. It should really take MemoryBuffers from the caller and handle this for them.

This revision is now accepted and ready to land.Feb 27 2017, 2:20 PM
thakis closed this revision.Feb 27 2017, 3:13 PM

r296408, thanks!