14a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved. 24a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 34a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// found in the LICENSE file. 44a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 54a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/common/multi_process_lock.h" 64a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 74a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <stdio.h> 84a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <sys/socket.h> 94a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <sys/un.h> 104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include <unistd.h> 114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/eintr_wrapper.h" 134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "base/logging.h" 144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochclass MultiProcessLockLinux : public MultiProcessLock { 164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch public: 174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch explicit MultiProcessLockLinux(const std::string& name) 184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch : name_(name), fd_(-1) { } 194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch virtual ~MultiProcessLockLinux() { 214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (fd_ != -1) { 224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch Unlock(); 234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch virtual bool TryLock() { 274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (fd_ != -1) { 284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch DLOG(ERROR) << "MultiProcessLock is already locked - " << name_; 294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return true; 304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (name_.length() > MULTI_PROCESS_LOCK_NAME_MAX_LEN) { 33201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch LOG(ERROR) << "Socket name too long (" << name_.length() 34201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch << " > " << MULTI_PROCESS_LOCK_NAME_MAX_LEN << ") - " << name_; 354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch struct sockaddr_un address; 394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // +1 for terminator, +1 for 0 in position 0 that makes it an 414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // abstract named socket. 424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // If this assert fails it is because sockaddr_un.sun_path size has been 434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // redefined and MULTI_PROCESS_LOCK_NAME_MAX_LEN can change accordingly. 444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch COMPILE_ASSERT(sizeof(address.sun_path) 454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch == MULTI_PROCESS_LOCK_NAME_MAX_LEN + 2, sun_path_size_changed); 464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch memset(&address, 0, sizeof(address)); 484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int print_length = snprintf(&address.sun_path[1], 494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch MULTI_PROCESS_LOCK_NAME_MAX_LEN + 1, 504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch "%s", name_.c_str()); 514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (print_length < 0 || 534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch print_length > static_cast<int>(MULTI_PROCESS_LOCK_NAME_MAX_LEN)) { 544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch PLOG(ERROR) << "Couldn't create sun_path - " << name_; 554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Must set the first character of the path to something non-zero 594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // before we call SUN_LEN which depends on strcpy working. 604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch address.sun_path[0] = '@'; 614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch size_t length = SUN_LEN(&address); 624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Reset the first character of the path back to zero so that 644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // bind returns an abstract name socket. 654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch address.sun_path[0] = 0; 664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch address.sun_family = AF_LOCAL; 674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0); 694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (socket_fd < 0) { 704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch PLOG(ERROR) << "Couldn't create socket - " << name_; 714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 724a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 744a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (bind(socket_fd, 754a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch reinterpret_cast<sockaddr *>(&address), 764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch length) == 0) { 774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch fd_ = socket_fd; 784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return true; 794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else { 804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch PLOG(ERROR) << "Couldn't bind socket - " 814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch << &(address.sun_path[1]) 824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch << " Length: " << length; 834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (HANDLE_EINTR(close(socket_fd)) < 0) { 844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch PLOG(ERROR) << "close"; 854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch virtual void Unlock() { 914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (fd_ == -1) { 924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch DLOG(ERROR) << "Over-unlocked MultiProcessLock - " << name_; 934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return; 944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (HANDLE_EINTR(close(fd_)) < 0) { 964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch PLOG(ERROR) << "close"; 974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch fd_ = -1; 994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 1004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch private: 1024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch std::string name_; 1034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch int fd_; 1044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch DISALLOW_COPY_AND_ASSIGN(MultiProcessLockLinux); 1054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}; 1064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben MurdochMultiProcessLock* MultiProcessLock::Create(const std::string &name) { 1084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return new MultiProcessLockLinux(name); 1094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 110