| 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;
|
| + }
|
| +}
|
| +
|
| +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
|
|
|