[llvm-commits] CVS: llvm/lib/Bytecode/Archive/Archive.cpp ArchiveWriter.cpp
Reid Spencer
reid at x10sys.com
Tue Nov 29 21:21:23 PST 2005
Changes in directory llvm/lib/Bytecode/Archive:
Archive.cpp updated: 1.9 -> 1.10
ArchiveWriter.cpp updated: 1.20 -> 1.21
---
Log message:
Fix a problem with llvm-ranlib that (on some platforms) caused the archive
file to become corrupted due to interactions between mmap'd memory segments
and file descriptors closing. The problem is completely avoiding by using
a third temporary file.
Patch provided by Evan Jones
---
Diffs of the changes: (+72 -36)
Archive.cpp | 24 ++++++++++++++-
ArchiveWriter.cpp | 84 ++++++++++++++++++++++++++++++++----------------------
2 files changed, 72 insertions(+), 36 deletions(-)
Index: llvm/lib/Bytecode/Archive/Archive.cpp
diff -u llvm/lib/Bytecode/Archive/Archive.cpp:1.9 llvm/lib/Bytecode/Archive/Archive.cpp:1.10
--- llvm/lib/Bytecode/Archive/Archive.cpp:1.9 Thu May 5 17:32:02 2005
+++ llvm/lib/Bytecode/Archive/Archive.cpp Tue Nov 29 23:21:10 2005
@@ -140,13 +140,28 @@
}
}
-// Archive destructor - just clean up memory
-Archive::~Archive() {
+void Archive::cleanUpMemory() {
// Shutdown the file mapping
if (mapfile) {
mapfile->close();
delete mapfile;
+
+ mapfile = 0;
+ base = 0;
}
+
+ // Forget the entire symbol table
+ symTab.clear();
+ symTabSize = 0;
+
+ firstFileOffset = 0;
+
+ // Free the foreign symbol table member
+ if (foreignST) {
+ delete foreignST;
+ foreignST = 0;
+ }
+
// Delete any ModuleProviders and ArchiveMember's we've allocated as a result
// of symbol table searches.
for (ModuleMap::iterator I=modules.begin(), E=modules.end(); I != E; ++I ) {
@@ -155,3 +170,8 @@
}
}
+// Archive destructor - just clean up memory
+Archive::~Archive() {
+ cleanUpMemory();
+}
+
Index: llvm/lib/Bytecode/Archive/ArchiveWriter.cpp
diff -u llvm/lib/Bytecode/Archive/ArchiveWriter.cpp:1.20 llvm/lib/Bytecode/Archive/ArchiveWriter.cpp:1.21
--- llvm/lib/Bytecode/Archive/ArchiveWriter.cpp:1.20 Thu Jul 7 22:08:58 2005
+++ llvm/lib/Bytecode/Archive/ArchiveWriter.cpp Tue Nov 29 23:21:10 2005
@@ -421,42 +421,58 @@
sys::MappedFile arch(TmpArchive);
const char* base = (const char*) arch.map();
- // Open the final file to write and check it.
- std::ofstream FinalFile(archPath.c_str(), io_mode);
- if ( !FinalFile.is_open() || FinalFile.bad() ) {
- throw std::string("Error opening archive file: ") + archPath.toString();
+ // Open another temporary file in order to avoid invalidating the mmapped data
+ sys::Path FinalFilePath = archPath;
+ FinalFilePath.createTemporaryFileOnDisk();
+ sys::RemoveFileOnSignal(FinalFilePath);
+ try {
+
+
+ std::ofstream FinalFile(FinalFilePath.c_str(), io_mode);
+ if ( !FinalFile.is_open() || FinalFile.bad() ) {
+ throw std::string("Error opening archive file: ") + FinalFilePath.toString();
+ }
+
+ // Write the file magic number
+ FinalFile << ARFILE_MAGIC;
+
+ // If there is a foreign symbol table, put it into the file now. Most
+ // ar(1) implementations require the symbol table to be first but llvm-ar
+ // can deal with it being after a foreign symbol table. This ensures
+ // compatibility with other ar(1) implementations as well as allowing the
+ // archive to store both native .o and LLVM .bc files, both indexed.
+ if (foreignST) {
+ writeMember(*foreignST, FinalFile, false, false, false);
+ }
+
+ // Put out the LLVM symbol table now.
+ writeSymbolTable(FinalFile);
+
+ // Copy the temporary file contents being sure to skip the file's magic
+ // number.
+ FinalFile.write(base + sizeof(ARFILE_MAGIC)-1,
+ arch.size()-sizeof(ARFILE_MAGIC)+1);
+
+ // Close up shop
+ FinalFile.close();
+ arch.close();
+
+ // Move the final file over top of TmpArchive
+ FinalFilePath.renamePathOnDisk(TmpArchive);
+ } catch (...) {
+ // Make sure we clean up.
+ if (FinalFilePath.exists())
+ FinalFilePath.eraseFromDisk();
+ throw;
}
-
- // Write the file magic number
- FinalFile << ARFILE_MAGIC;
-
- // If there is a foreign symbol table, put it into the file now. Most
- // ar(1) implementations require the symbol table to be first but llvm-ar
- // can deal with it being after a foreign symbol table. This ensures
- // compatibility with other ar(1) implementations as well as allowing the
- // archive to store both native .o and LLVM .bc files, both indexed.
- if (foreignST) {
- writeMember(*foreignST, FinalFile, false, false, false);
- }
-
- // Put out the LLVM symbol table now.
- writeSymbolTable(FinalFile);
-
- // Copy the temporary file contents being sure to skip the file's magic
- // number.
- FinalFile.write(base + sizeof(ARFILE_MAGIC)-1,
- arch.size()-sizeof(ARFILE_MAGIC)+1);
-
- // Close up shop
- FinalFile.close();
- arch.close();
- TmpArchive.eraseFromDisk();
-
- } else {
- // We don't have to insert the symbol table, so just renaming the temp
- // file to the correct name will suffice.
- TmpArchive.renamePathOnDisk(archPath);
}
+
+ // Before we replace the actual archive, we need to forget all the
+ // members, since they point to data in that old archive. We need to do
+ // we cannot replace an open file on Windows.
+ cleanUpMemory();
+
+ TmpArchive.renamePathOnDisk(archPath);
} catch (...) {
// Make sure we clean up.
if (TmpArchive.exists())
More information about the llvm-commits
mailing list