- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / common / multi_process_lock_linux.cc
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.
4
5 #include "chrome/common/multi_process_lock.h"
6
7 #include <stdio.h>
8 #include <sys/socket.h>
9 #include <sys/un.h>
10 #include <unistd.h>
11
12 #include "base/compiler_specific.h"
13 #include "base/logging.h"
14 #include "base/posix/eintr_wrapper.h"
15
16 class MultiProcessLockLinux : public MultiProcessLock {
17  public:
18   explicit MultiProcessLockLinux(const std::string& name)
19       : name_(name), fd_(-1) { }
20
21   virtual ~MultiProcessLockLinux() {
22     if (fd_ != -1) {
23       Unlock();
24     }
25   }
26
27   virtual bool TryLock() OVERRIDE {
28     struct sockaddr_un address;
29
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;
33
34     if (fd_ != -1) {
35       DLOG(ERROR) << "MultiProcessLock is already locked - " << name_;
36       return true;
37     }
38
39     if (name_.length() > max_len) {
40       LOG(ERROR) << "Socket name too long (" << name_.length()
41                  << " > " << max_len << ") - " << name_;
42       return false;
43     }
44
45     memset(&address, 0, sizeof(address));
46     int print_length = snprintf(&address.sun_path[1],
47                                 max_len + 1,
48                                 "%s", name_.c_str());
49
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;
54     }
55
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);
60
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;
65
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;
70     }
71
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 (HANDLE_EINTR(close(socket_fd)) < 0) {
82         PLOG(ERROR) << "close";
83       }
84       return false;
85     }
86   }
87
88   virtual void Unlock() OVERRIDE {
89     if (fd_ == -1) {
90       DLOG(ERROR) << "Over-unlocked MultiProcessLock - " << name_;
91       return;
92     }
93     if (HANDLE_EINTR(close(fd_)) < 0) {
94       DPLOG(ERROR) << "close";
95     }
96     fd_ = -1;
97   }
98
99  private:
100   std::string name_;
101   int fd_;
102   DISALLOW_COPY_AND_ASSIGN(MultiProcessLockLinux);
103 };
104
105 MultiProcessLock* MultiProcessLock::Create(const std::string &name) {
106   return new MultiProcessLockLinux(name);
107 }