summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Object/ArchiveWriter.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2016-05-09 13:31:11 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2016-05-09 13:31:11 +0000
commit484983f453c1c29725a02262124beea52a7bbd0b (patch)
tree6b2027092a99f8e3086bad284b9fad0bd9eab41b /llvm/lib/Object/ArchiveWriter.cpp
parentaf742d51ad622b158f71523369fc8998b35ffb3c (diff)
downloadbcm5719-llvm-484983f453c1c29725a02262124beea52a7bbd0b.tar.gz
bcm5719-llvm-484983f453c1c29725a02262124beea52a7bbd0b.zip
Fix bug where temporary file would be left behind every time an archive was updated.
When updating an existing archive, llvm-ar opens the old archive into a `MemoryBuffer`, does its thing, and writes the results to a temporary file. That file is then renamed to the original archive filename, thus replacing it with the updated contents. However, on Windows at least, what would happen is that the `MemoryBuffer` for the old archive would actually be an mmap'ed view of the file, so when it came time to do the rename via Win32's `ReplaceFile`, it would succeed but would be unable to fully replace the file since there would still be a handle open on it; instead, the old version got renamed to a random temporary name and left behind. Patch by Cameron! llvm-svn: 268916
Diffstat (limited to 'llvm/lib/Object/ArchiveWriter.cpp')
-rw-r--r--llvm/lib/Object/ArchiveWriter.cpp16
1 files changed, 15 insertions, 1 deletions
diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp
index 1ae14f24178..93e285cf674 100644
--- a/llvm/lib/Object/ArchiveWriter.cpp
+++ b/llvm/lib/Object/ArchiveWriter.cpp
@@ -307,7 +307,8 @@ std::pair<StringRef, std::error_code>
llvm::writeArchive(StringRef ArcName,
std::vector<NewArchiveIterator> &NewMembers,
bool WriteSymtab, object::Archive::Kind Kind,
- bool Deterministic, bool Thin) {
+ bool Deterministic, bool Thin,
+ std::unique_ptr<MemoryBuffer> OldArchiveBuf) {
assert((!Thin || Kind == object::Archive::K_GNU) &&
"Only the gnu format has a thin mode");
SmallString<128> TmpArchive;
@@ -443,6 +444,19 @@ llvm::writeArchive(StringRef ArcName,
Output.keep();
Out.close();
+
+ // At this point, we no longer need whatever backing memory
+ // was used to generate the NewMembers. On Windows, this buffer
+ // could be a mapped view of the file we want to replace (if
+ // we're updating an existing archive, say). In that case, the
+ // rename would still succeed, but it would leave behind a
+ // temporary file (actually the original file renamed) because
+ // a file cannot be deleted while there's a handle open on it,
+ // only renamed. So by freeing this buffer, this ensures that
+ // the last open handle on the destination file, if any, is
+ // closed before we attempt to rename.
+ OldArchiveBuf.reset();
+
sys::fs::rename(TmpArchive, ArcName);
return std::make_pair("", std::error_code());
}
OpenPOWER on IntegriCloud