summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Support/Path.cpp
diff options
context:
space:
mode:
authorBob Haarman <llvm@inglorion.net>2018-08-02 17:41:38 +0000
committerBob Haarman <llvm@inglorion.net>2018-08-02 17:41:38 +0000
commit9b36f51ae7618e2684d54c99fc88a379462dbeec (patch)
treedeaab7995e513db7d1aed7c4389ecd6f9ff4b6e7 /llvm/lib/Support/Path.cpp
parent41d7047de59f9c40067658df900ccc9d58eb7a3e (diff)
downloadbcm5719-llvm-9b36f51ae7618e2684d54c99fc88a379462dbeec.tar.gz
bcm5719-llvm-9b36f51ae7618e2684d54c99fc88a379462dbeec.zip
[Support] fix TempFile infinite loop and permission denied errors
Summary: On Windows, TempFile::create() was prone to failing with permission denied errors when a process created many tempfiles without providing a model large enough to accommodate them. There was also a problem with createUniqueEntity getting into an infinite loop when all names permitted by the model are in use. This change fixes both of these problems and adds a unit test for them. Reviewers: pcc, rnk, zturner Reviewed By: zturner Subscribers: inglorion, hiraditya, llvm-commits Differential Revision: https://reviews.llvm.org/D50126 llvm-svn: 338745
Diffstat (limited to 'llvm/lib/Support/Path.cpp')
-rw-r--r--llvm/lib/Support/Path.cpp77
1 files changed, 42 insertions, 35 deletions
diff --git a/llvm/lib/Support/Path.cpp b/llvm/lib/Support/Path.cpp
index 098230290ed..adba21b3bcd 100644
--- a/llvm/lib/Support/Path.cpp
+++ b/llvm/lib/Support/Path.cpp
@@ -190,48 +190,55 @@ createUniqueEntity(const Twine &Model, int &ResultFD,
ResultPath.push_back(0);
ResultPath.pop_back();
-retry_random_path:
- // Replace '%' with random chars.
- for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
- if (ModelStorage[i] == '%')
- ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
- }
-
- // Try to open + create the file.
- switch (Type) {
- case FS_File: {
- if (std::error_code EC =
- sys::fs::openFileForReadWrite(Twine(ResultPath.begin()), ResultFD,
- sys::fs::CD_CreateNew, Flags, Mode)) {
- if (EC == errc::file_exists)
- goto retry_random_path;
- return EC;
+ // Limit the number of attempts we make, so that we don't infinite loop when
+ // we run out of filenames that fit the model.
+ std::error_code EC;
+ for (int Retries = 128; Retries > 0; --Retries) {
+ // Replace '%' with random chars.
+ for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) {
+ if (ModelStorage[i] == '%')
+ ResultPath[i] =
+ "0123456789abcdef"[sys::Process::GetRandomNumber() & 15];
}
- return std::error_code();
- }
+ // Try to open + create the file.
+ switch (Type) {
+ case FS_File: {
+ EC = sys::fs::openFileForReadWrite(Twine(ResultPath.begin()), ResultFD,
+ sys::fs::CD_CreateNew, Flags, Mode);
+ if (EC) {
+ // errc::permission_denied happens on Windows when we try to open a file
+ // that has been marked for deletion.
+ if (EC == errc::file_exists || EC == errc::permission_denied)
+ continue;
+ return EC;
+ }
- case FS_Name: {
- std::error_code EC =
- sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist);
- if (EC == errc::no_such_file_or_directory)
return std::error_code();
- if (EC)
- return EC;
- goto retry_random_path;
- }
+ }
- case FS_Dir: {
- if (std::error_code EC =
- sys::fs::create_directory(ResultPath.begin(), false)) {
- if (EC == errc::file_exists)
- goto retry_random_path;
- return EC;
+ case FS_Name: {
+ EC = sys::fs::access(ResultPath.begin(), sys::fs::AccessMode::Exist);
+ if (EC == errc::no_such_file_or_directory)
+ return std::error_code();
+ if (EC)
+ return EC;
+ continue;
}
- return std::error_code();
- }
+
+ case FS_Dir: {
+ EC = sys::fs::create_directory(ResultPath.begin(), false);
+ if (EC) {
+ if (EC == errc::file_exists)
+ continue;
+ return EC;
+ }
+ return std::error_code();
+ }
+ }
+ llvm_unreachable("Invalid Type");
}
- llvm_unreachable("Invalid Type");
+ return EC;
}
namespace llvm {
OpenPOWER on IntegriCloud