15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/multi_process_lock.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/un.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MultiProcessLockLinux : public MultiProcessLock { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit MultiProcessLockLinux(const std::string& name) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : name_(name), fd_(-1) { } 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~MultiProcessLockLinux() { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fd_ != -1) { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Unlock(); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool TryLock() OVERRIDE { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_un address; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // +1 for terminator, +1 for 0 in position 0 that makes it an 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // abstract named socket. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t max_len = sizeof(address.sun_path) - 2; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fd_ != -1) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "MultiProcessLock is already locked - " << name_; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name_.length() > max_len) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Socket name too long (" << name_.length() 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " > " << max_len << ") - " << name_; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&address, 0, sizeof(address)); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int print_length = snprintf(&address.sun_path[1], 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_len + 1, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%s", name_.c_str()); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (print_length < 0 || 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print_length > static_cast<int>(max_len)) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "Couldn't create sun_path - " << name_; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Must set the first character of the path to something non-zero 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // before we call SUN_LEN which depends on strcpy working. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) address.sun_path[0] = '@'; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t length = SUN_LEN(&address); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset the first character of the path back to zero so that 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bind returns an abstract name socket. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) address.sun_path[0] = 0; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) address.sun_family = AF_LOCAL; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_fd < 0) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "Couldn't create socket - " << name_; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bind(socket_fd, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<sockaddr *>(&address), 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length) == 0) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fd_ = socket_fd; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "Couldn't bind socket - " 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << &(address.sun_path[1]) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " Length: " << length; 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (IGNORE_EINTR(close(socket_fd)) < 0) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "close"; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void Unlock() OVERRIDE { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fd_ == -1) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(ERROR) << "Over-unlocked MultiProcessLock - " << name_; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (IGNORE_EINTR(close(fd_)) < 0) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DPLOG(ERROR) << "close"; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fd_ = -1; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string name_; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd_; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MultiProcessLockLinux); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MultiProcessLock* MultiProcessLock::Create(const std::string &name) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new MultiProcessLockLinux(name); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 108