[lld] r280510 - Remove temoprary files.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 2 10:34:18 PDT 2016
Author: ruiu
Date: Fri Sep 2 12:34:17 2016
New Revision: 280510
URL: http://llvm.org/viewvc/llvm-project?rev=280510&view=rev
Log:
Remove temoprary files.
Previously, we created temporary files using llvm::sys::fs::createTemporaryFile
and removed them using llvm::FileRemover. This is error-prone as it is easy to
forget creating FileRemover instances after creating temporary files.
There is actually a temporary file leak bug.
This patch introduces a new class, TemporaryFile, to manage temporary files
in the RAII style.
Differential Revision: https://reviews.llvm.org/D24176
Modified:
lld/trunk/COFF/DriverUtils.cpp
Modified: lld/trunk/COFF/DriverUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DriverUtils.cpp?rev=280510&r1=280509&r2=280510&view=diff
==============================================================================
--- lld/trunk/COFF/DriverUtils.cpp (original)
+++ lld/trunk/COFF/DriverUtils.cpp Fri Sep 2 12:34:17 2016
@@ -279,18 +279,54 @@ static void quoteAndPrint(raw_ostream &O
}
}
+// An RAII temporary file class that automatically removes a temporary file.
+namespace {
+class TemporaryFile {
+public:
+ TemporaryFile(StringRef Prefix, StringRef Extn) {
+ SmallString<128> S;
+ if (auto EC = sys::fs::createTemporaryFile("lld-" + Prefix, Extn, S))
+ fatal(EC, "cannot create a temporary file");
+ Path = S.str();
+ }
+
+ TemporaryFile(TemporaryFile &&Obj) {
+ std::swap(Path, Obj.Path);
+ }
+
+ ~TemporaryFile() {
+ if (Path.empty())
+ return;
+ if (sys::fs::remove(Path))
+ fatal("failed to remove " + Path);
+ }
+
+ // Returns a memory buffer of this temporary file.
+ // Note that this function does not leave the file open,
+ // so it is safe to remove the file immediately after this function
+ // is called (you cannot remove an opened file on Windows.)
+ std::unique_ptr<MemoryBuffer> getMemoryBuffer() {
+ // IsVolatileSize=true forces MemoryBuffer to not use mmap().
+ return check(MemoryBuffer::getFile(Path, /*FileSize=*/-1,
+ /*RequiresNullTerminator=*/false,
+ /*IsVolatileSize=*/true),
+ "could not open " + Path);
+ }
+
+ std::string Path;
+};
+}
+
// Create the default manifest file as a temporary file.
-static std::string createDefaultXml() {
+TemporaryFile createDefaultXml() {
// Create a temporary file.
- SmallString<128> Path;
- if (auto EC = sys::fs::createTemporaryFile("tmp", "manifest", Path))
- fatal(EC, "cannot create a temporary file");
+ TemporaryFile File("defaultxml", "manifest");
// Open the temporary file for writing.
std::error_code EC;
- llvm::raw_fd_ostream OS(Path, EC, sys::fs::F_Text);
+ llvm::raw_fd_ostream OS(File.Path, EC, sys::fs::F_Text);
if (EC)
- fatal(EC, "failed to open " + Path);
+ fatal(EC, "failed to open " + File.Path);
// Emit the XML. Note that we do *not* verify that the XML attributes are
// syntactically correct. This is intentional for link.exe compatibility.
@@ -316,56 +352,48 @@ static std::string createDefaultXml() {
}
OS << "</assembly>\n";
OS.close();
- return StringRef(Path);
+ return File;
}
static std::string readFile(StringRef Path) {
std::unique_ptr<MemoryBuffer> MB =
check(MemoryBuffer::getFile(Path), "could not open " + Path);
- std::unique_ptr<MemoryBuffer> Buf(std::move(MB));
- return Buf->getBuffer();
+ return MB->getBuffer();
}
static std::string createManifestXml() {
// Create the default manifest file.
- std::string Path1 = createDefaultXml();
+ TemporaryFile File1 = createDefaultXml();
if (Config->ManifestInput.empty())
- return readFile(Path1);
+ return readFile(File1.Path);
// If manifest files are supplied by the user using /MANIFESTINPUT
// option, we need to merge them with the default manifest.
- SmallString<128> Path2;
- if (auto EC = sys::fs::createTemporaryFile("tmp", "manifest", Path2))
- fatal(EC, "cannot create a temporary file");
- FileRemover Remover1(Path1);
- FileRemover Remover2(Path2);
+ TemporaryFile File2("user", "manifest");
Executor E("mt.exe");
E.add("/manifest");
- E.add(Path1);
+ E.add(File1.Path);
for (StringRef Filename : Config->ManifestInput) {
E.add("/manifest");
E.add(Filename);
}
E.add("/nologo");
- E.add("/out:" + StringRef(Path2));
+ E.add("/out:" + StringRef(File2.Path));
E.run();
- return readFile(Path2);
+ return readFile(File2.Path);
}
// Create a resource file containing a manifest XML.
std::unique_ptr<MemoryBuffer> createManifestRes() {
// Create a temporary file for the resource script file.
- SmallString<128> RCPath;
- if (auto EC = sys::fs::createTemporaryFile("tmp", "rc", RCPath))
- fatal(EC, "cannot create a temporary file");
- FileRemover RCRemover(RCPath);
+ TemporaryFile RCFile("manifest", "rc");
// Open the temporary file for writing.
std::error_code EC;
- llvm::raw_fd_ostream Out(RCPath, EC, sys::fs::F_Text);
+ llvm::raw_fd_ostream Out(RCFile.Path, EC, sys::fs::F_Text);
if (EC)
- fatal(EC, "failed to open " + RCPath);
+ fatal(EC, "failed to open " + RCFile.Path);
// Write resource script to the RC file.
Out << "#define LANG_ENGLISH 9\n"
@@ -379,17 +407,15 @@ std::unique_ptr<MemoryBuffer> createMani
Out.close();
// Create output resource file.
- SmallString<128> ResPath;
- if (auto EC = sys::fs::createTemporaryFile("tmp", "res", ResPath))
- fatal(EC, "cannot create a temporary file");
+ TemporaryFile ResFile("output-resource", "res");
Executor E("rc.exe");
E.add("/fo");
- E.add(ResPath.str());
+ E.add(ResFile.Path);
E.add("/nologo");
- E.add(RCPath.str());
+ E.add(RCFile.Path);
E.run();
- return check(MemoryBuffer::getFile(ResPath), "could not open " + ResPath);
+ return ResFile.getMemoryBuffer();
}
void createSideBySideManifest() {
@@ -555,20 +581,18 @@ void checkFailIfMismatch(StringRef Arg)
std::unique_ptr<MemoryBuffer>
convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) {
// Create an output file path.
- SmallString<128> Path;
- if (auto EC = llvm::sys::fs::createTemporaryFile("resource", "obj", Path))
- fatal(EC, "could not create temporary file");
+ TemporaryFile File("resource-file", "obj");
// Execute cvtres.exe.
Executor E("cvtres.exe");
E.add("/machine:" + machineToStr(Config->Machine));
E.add("/readonly");
E.add("/nologo");
- E.add("/out:" + Path);
+ E.add("/out:" + Twine(File.Path));
for (MemoryBufferRef MB : MBs)
E.add(MB.getBufferIdentifier());
E.run();
- return check(MemoryBuffer::getFile(Path), "could not open " + Path);
+ return File.getMemoryBuffer();
}
// Create OptTable
More information about the llvm-commits
mailing list