Chromium Code Reviews| Index: rlz/lib/recursive_cross_process_lock_posix.cc |
| diff --git a/rlz/lib/recursive_cross_process_lock_posix.cc b/rlz/lib/recursive_cross_process_lock_posix.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..071bf8ced662fed508397db103c273f88f154844 |
| --- /dev/null |
| +++ b/rlz/lib/recursive_cross_process_lock_posix.cc |
| @@ -0,0 +1,81 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "rlz/lib/recursive_cross_process_lock_posix.h" |
| + |
| +#include <sys/file.h> |
| +#include <sys/types.h> |
| +#include <sys/stat.h> |
| +#include <fcntl.h> |
| + |
| +#include "base/file_path.h" |
| +#include "base/logging.h" |
| +#include "base/posix/eintr_wrapper.h" |
| + |
| +namespace rlz_lib { |
| + |
| +bool RecursiveCrossProcessLock::TryGetCrossProcessLock( |
| + const FilePath& lock_filename) { |
| + bool just_got_lock = false; |
| + |
| + // Emulate a recursive mutex with a non-recursive one. |
| + if (pthread_mutex_trylock(&recursive_lock_) == EBUSY) { |
| + if (pthread_equal(pthread_self(), locking_thread_) == 0) { |
| + // Some other thread has the lock, wait for it. |
| + pthread_mutex_lock(&recursive_lock_); |
| + CHECK(locking_thread_ == 0); |
| + just_got_lock = true; |
| + } |
| + } else { |
| + just_got_lock = true; |
| + } |
| + |
| + locking_thread_ = pthread_self(); |
| + |
| + // Try to acquire file lock. |
| + if (just_got_lock) { |
| + const int kMaxTimeoutMS = 5000; // Matches Windows. |
| + const int kSleepPerTryMS = 200; |
| + |
| + CHECK(file_lock_ == -1); |
| + file_lock_ = open(lock_filename.value().c_str(), O_RDWR | O_CREAT, 0666); |
| + if (file_lock_ == -1) { |
| + perror("open"); |
| + return false; |
| + } |
| + |
| + int flock_result = -1; |
| + int elapsed_ms = 0; |
| + while ((flock_result = |
| + HANDLE_EINTR(flock(file_lock_, LOCK_EX | LOCK_NB))) == -1 && |
| + errno == EWOULDBLOCK && |
| + elapsed_ms < kMaxTimeoutMS) { |
| + usleep(kSleepPerTryMS * 1000); |
| + elapsed_ms += kSleepPerTryMS; |
| + } |
| + |
| + if (flock_result == -1) { |
| + perror("flock"); |
| + ignore_result(HANDLE_EINTR(close(file_lock_))); |
| + file_lock_ = -1; |
| + return false; |
| + } |
| + return true; |
| + } else { |
| + return file_lock_ != -1; |
|
Roger Tawa OOO till Jul 10th
2012/11/26 19:16:51
why not a DCHECK as well? Under what normal situa
Ivan Korotkov
2012/11/27 11:37:25
I think the point of this line was that if the top
|
| + } |
| +} |
| + |
| +void RecursiveCrossProcessLock::ReleaseLock() { |
| + if (file_lock_ != -1) { |
| + ignore_result(HANDLE_EINTR(flock(file_lock_, LOCK_UN))); |
| + ignore_result(HANDLE_EINTR(close(file_lock_))); |
| + file_lock_ = -1; |
| + } |
| + |
| + locking_thread_ = 0; |
| + pthread_mutex_unlock(&recursive_lock_); |
| +} |
| + |
| +} // namespace rlz_lib |