Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / chrome / common / multi_process_lock_linux.cc
blob49ec99a896f1ff30fb0d939ee3cfe7f65b9b41a8
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/common/multi_process_lock.h"
7 #include <stdio.h>
8 #include <sys/socket.h>
9 #include <sys/un.h>
10 #include <unistd.h>
12 #include "base/compiler_specific.h"
13 #include "base/logging.h"
14 #include "base/posix/eintr_wrapper.h"
16 class MultiProcessLockLinux : public MultiProcessLock {
17 public:
18 explicit MultiProcessLockLinux(const std::string& name)
19 : name_(name), fd_(-1) { }
21 ~MultiProcessLockLinux() override {
22 if (fd_ != -1) {
23 Unlock();
27 bool TryLock() override {
28 struct sockaddr_un address;
30 // +1 for terminator, +1 for 0 in position 0 that makes it an
31 // abstract named socket.
32 const size_t max_len = sizeof(address.sun_path) - 2;
34 if (fd_ != -1) {
35 DLOG(ERROR) << "MultiProcessLock is already locked - " << name_;
36 return true;
39 if (name_.length() > max_len) {
40 LOG(ERROR) << "Socket name too long (" << name_.length()
41 << " > " << max_len << ") - " << name_;
42 return false;
45 memset(&address, 0, sizeof(address));
46 int print_length = snprintf(&address.sun_path[1],
47 max_len + 1,
48 "%s", name_.c_str());
50 if (print_length < 0 ||
51 print_length > static_cast<int>(max_len)) {
52 PLOG(ERROR) << "Couldn't create sun_path - " << name_;
53 return false;
56 // Must set the first character of the path to something non-zero
57 // before we call SUN_LEN which depends on strcpy working.
58 address.sun_path[0] = '@';
59 size_t length = SUN_LEN(&address);
61 // Reset the first character of the path back to zero so that
62 // bind returns an abstract name socket.
63 address.sun_path[0] = 0;
64 address.sun_family = AF_LOCAL;
66 int socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
67 if (socket_fd < 0) {
68 PLOG(ERROR) << "Couldn't create socket - " << name_;
69 return false;
72 if (bind(socket_fd,
73 reinterpret_cast<sockaddr *>(&address),
74 length) == 0) {
75 fd_ = socket_fd;
76 return true;
77 } else {
78 DVLOG(1) << "Couldn't bind socket - "
79 << &(address.sun_path[1])
80 << " Length: " << length;
81 if (IGNORE_EINTR(close(socket_fd)) < 0) {
82 PLOG(ERROR) << "close";
84 return false;
88 void Unlock() override {
89 if (fd_ == -1) {
90 DLOG(ERROR) << "Over-unlocked MultiProcessLock - " << name_;
91 return;
93 if (IGNORE_EINTR(close(fd_)) < 0) {
94 DPLOG(ERROR) << "close";
96 fd_ = -1;
99 private:
100 std::string name_;
101 int fd_;
102 DISALLOW_COPY_AND_ASSIGN(MultiProcessLockLinux);
105 MultiProcessLock* MultiProcessLock::Create(const std::string &name) {
106 return new MultiProcessLockLinux(name);