summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Langmuir <blangmuir@apple.com>2015-06-29 17:08:41 +0000
committerBen Langmuir <blangmuir@apple.com>2015-06-29 17:08:41 +0000
commit63aa8c5d282e7725d2e33203abd099f7d128ef9d (patch)
treed91935cd35cd3fe2359b31558c4a6060d0abc34f
parent8f6f4285f3aa4fdcbbb378e9e399326232c0645a (diff)
downloadbcm5719-llvm-63aa8c5d282e7725d2e33203abd099f7d128ef9d.tar.gz
bcm5719-llvm-63aa8c5d282e7725d2e33203abd099f7d128ef9d.zip
Clean up unique lock files on signal and always release the lock
Make sure to remove the unique lock file, which is what the .lock symlink points to, if there is a signal while the lock is held. This will release the lock, since the symlink will point to nothing (already tested in unit tests). For good measure, also clean up the unique lock file if there is an error or signal before the lock is acquired. I will add a clang test. rdar://problem/21512307 llvm-svn: 240967
-rw-r--r--llvm/lib/Support/LockFileManager.cpp41
1 files changed, 40 insertions, 1 deletions
diff --git a/llvm/lib/Support/LockFileManager.cpp b/llvm/lib/Support/LockFileManager.cpp
index d07c5f0f682..95e0ece9245 100644
--- a/llvm/lib/Support/LockFileManager.cpp
+++ b/llvm/lib/Support/LockFileManager.cpp
@@ -12,6 +12,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Signals.h"
#include <sys/stat.h>
#include <sys/types.h>
#if LLVM_ON_WIN32
@@ -69,6 +70,35 @@ bool LockFileManager::processStillExecuting(StringRef Hostname, int PID) {
return true;
}
+namespace {
+/// An RAII helper object ensure that the unique lock file is removed.
+///
+/// Ensures that if there is an error or a signal before we finish acquiring the
+/// lock, the unique file will be removed. And if we successfully take the lock,
+/// the signal handler is left in place so that signals while the lock is held
+/// will remove the unique lock file. The caller should ensure there is a
+/// matching call to sys::DontRemoveFileOnSignal when the lock is released.
+class RemoveUniqueLockFileOnSignal {
+ StringRef Filename;
+ bool RemoveImmediately;
+public:
+ RemoveUniqueLockFileOnSignal(StringRef Name)
+ : Filename(Name), RemoveImmediately(true) {
+ sys::RemoveFileOnSignal(Filename, nullptr);
+ }
+ ~RemoveUniqueLockFileOnSignal() {
+ if (!RemoveImmediately) {
+ // Leave the signal handler enabled. It will be removed when the lock is
+ // released.
+ return;
+ }
+ sys::fs::remove(Filename);
+ sys::DontRemoveFileOnSignal(Filename);
+ }
+ void lockAcquired() { RemoveImmediately = false; }
+};
+} // end anonymous namespace
+
LockFileManager::LockFileManager(StringRef FileName)
{
this->FileName = FileName;
@@ -119,12 +149,18 @@ LockFileManager::LockFileManager(StringRef FileName)
}
}
+ // Clean up the unique file on signal, which also releases the lock if it is
+ // held since the .lock symlink will point to a nonexistent file.
+ RemoveUniqueLockFileOnSignal RemoveUniqueFile(UniqueLockFileName);
+
while (1) {
// Create a link from the lock file name. If this succeeds, we're done.
std::error_code EC =
sys::fs::create_link(UniqueLockFileName, LockFileName);
- if (!EC)
+ if (!EC) {
+ RemoveUniqueFile.lockAcquired();
return;
+ }
if (EC != errc::file_exists) {
Error = EC;
@@ -171,6 +207,9 @@ LockFileManager::~LockFileManager() {
// Since we own the lock, remove the lock file and our own unique lock file.
sys::fs::remove(LockFileName);
sys::fs::remove(UniqueLockFileName);
+ // The unique file is now gone, so remove it from the signal handler. This
+ // matches a sys::RemoveFileOnSignal() in LockFileManager().
+ sys::DontRemoveFileOnSignal(UniqueLockFileName);
}
LockFileManager::WaitForUnlockResult LockFileManager::waitForUnlock() {
OpenPOWER on IntegriCloud