| Index: chrome/browser/process_singleton_linux.cc
|
| diff --git a/chrome/browser/process_singleton_linux.cc b/chrome/browser/process_singleton_linux.cc
|
| index fa66e1704c9dcdd28278e17b38a42704b45efeec..d4fb0b30086c1b5e096ddf1981f67be64d71131c 100644
|
| --- a/chrome/browser/process_singleton_linux.cc
|
| +++ b/chrome/browser/process_singleton_linux.cc
|
| @@ -60,6 +60,7 @@
|
| #include "base/command_line.h"
|
| #include "base/eintr_wrapper.h"
|
| #include "base/file_path.h"
|
| +#include "base/file_util.h"
|
| #include "base/logging.h"
|
| #include "base/message_loop.h"
|
| #include "base/path_service.h"
|
| @@ -229,43 +230,29 @@ void SetupSocket(const std::string& path, int* sock, struct sockaddr_un* addr) {
|
| SetupSockAddr(path, addr);
|
| }
|
|
|
| -// Read a symbolic link, return empty string if given path is not a
|
| -// symbol link. This version does not interpret the errno, leaving
|
| -// the caller to do so.
|
| -bool ReadLinkSilent(const std::string& path, std::string* output) {
|
| - char buf[PATH_MAX];
|
| - ssize_t len = readlink(path.c_str(), buf, PATH_MAX);
|
| - if (len >= 0) {
|
| - output->assign(buf, len);
|
| - return true;
|
| - }
|
| - output->clear();
|
| - return false;
|
| -}
|
| -
|
| // Read a symbolic link, return empty string if given path is not a symbol link.
|
| -std::string ReadLink(const std::string& path) {
|
| - std::string target;
|
| - if (!ReadLinkSilent(path, &target)) {
|
| +FilePath ReadLink(const FilePath& path) {
|
| + FilePath target;
|
| + if (!file_util::ReadSymbolicLink(path, &target)) {
|
| // The only errno that should occur is ENOENT.
|
| if (errno != 0 && errno != ENOENT)
|
| - PLOG(ERROR) << "readlink(" << path << ") failed";
|
| + PLOG(ERROR) << "readlink(" << path.value() << ") failed";
|
| }
|
| return target;
|
| }
|
|
|
| // Unlink a path. Return true on success.
|
| -bool UnlinkPath(const std::string& path) {
|
| - int rv = unlink(path.c_str());
|
| +bool UnlinkPath(const FilePath& path) {
|
| + int rv = unlink(path.value().c_str());
|
| if (rv < 0 && errno != ENOENT)
|
| - PLOG(ERROR) << "Failed to unlink " << path;
|
| + PLOG(ERROR) << "Failed to unlink " << path.value();
|
|
|
| return rv == 0;
|
| }
|
|
|
| // Create a symlink. Returns true on success.
|
| -bool SymlinkPath(const std::string& target, const std::string& path) {
|
| - if (symlink(target.c_str(), path.c_str()) < 0) {
|
| +bool SymlinkPath(const FilePath& target, const FilePath& path) {
|
| + if (!file_util::CreateSymbolicLink(target, path)) {
|
| // Double check the value in case symlink suceeded but we got an incorrect
|
| // failure due to NFS packet loss & retry.
|
| int saved_errno = errno;
|
| @@ -273,7 +260,7 @@ bool SymlinkPath(const std::string& target, const std::string& path) {
|
| // If we failed to create the lock, most likely another instance won the
|
| // startup race.
|
| errno = saved_errno;
|
| - PLOG(ERROR) << "Failed to create " << path;
|
| + PLOG(ERROR) << "Failed to create " << path.value();
|
| return false;
|
| }
|
| }
|
| @@ -282,10 +269,10 @@ bool SymlinkPath(const std::string& target, const std::string& path) {
|
|
|
| // Extract the hostname and pid from the lock symlink.
|
| // Returns true if the lock existed.
|
| -bool ParseLockPath(const std::string& path,
|
| +bool ParseLockPath(const FilePath& path,
|
| std::string* hostname,
|
| int* pid) {
|
| - std::string real_path = ReadLink(path);
|
| + std::string real_path = ReadLink(path).value();
|
| if (real_path.empty())
|
| return false;
|
|
|
| @@ -350,13 +337,13 @@ bool IsSameChromeInstance(pid_t pid) {
|
| // If the process is part of the same chrome instance, unlink the lock file and
|
| // return true without killing it.
|
| // If the process is on a different host, return false.
|
| -bool KillProcessByLockPath(const std::string& path) {
|
| +bool KillProcessByLockPath(const FilePath& path) {
|
| std::string hostname;
|
| int pid;
|
| ParseLockPath(path, &hostname, &pid);
|
|
|
| if (!hostname.empty() && hostname != net::GetHostName()) {
|
| - DisplayProfileInUseError(path, hostname, pid);
|
| + DisplayProfileInUseError(path.value(), hostname, pid);
|
| return false;
|
| }
|
| UnlinkPath(path);
|
| @@ -374,7 +361,7 @@ bool KillProcessByLockPath(const std::string& path) {
|
| return true;
|
| }
|
|
|
| - LOG(ERROR) << "Failed to extract pid from path: " << path;
|
| + LOG(ERROR) << "Failed to extract pid from path: " << path.value();
|
| return true;
|
| }
|
|
|
| @@ -402,21 +389,21 @@ std::string GenerateCookie() {
|
| return base::Uint64ToString(base::RandUint64());
|
| }
|
|
|
| -bool CheckCookie(const FilePath& path, const std::string& cookie) {
|
| - return (cookie == ReadLink(path.value()));
|
| +bool CheckCookie(const FilePath& path, const FilePath& cookie) {
|
| + return (cookie == ReadLink(path));
|
| }
|
|
|
| bool ConnectSocket(ScopedSocket* socket,
|
| const FilePath& socket_path,
|
| const FilePath& cookie_path) {
|
| - std::string socket_target;
|
| - if (ReadLinkSilent(socket_path.value(), &socket_target)) {
|
| + FilePath socket_target;
|
| + if (file_util::ReadSymbolicLink(socket_path, &socket_target)) {
|
| // It's a symlink. Read the cookie.
|
| - std::string cookie = ReadLink(cookie_path.value());
|
| + FilePath cookie = ReadLink(cookie_path);
|
| if (cookie.empty())
|
| return false;
|
| - FilePath remote_cookie = FilePath(socket_target).DirName().
|
| - Append(chrome::kSingletonCookieFilename);
|
| + FilePath remote_cookie = socket_target.DirName().
|
| + Append(chrome::kSingletonCookieFilename);
|
| // Verify the cookie before connecting.
|
| if (!CheckCookie(remote_cookie, cookie))
|
| return false;
|
| @@ -794,14 +781,14 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
|
|
|
| std::string hostname;
|
| int pid;
|
| - if (!ParseLockPath(lock_path_.value(), &hostname, &pid)) {
|
| + if (!ParseLockPath(lock_path_, &hostname, &pid)) {
|
| // No lockfile exists.
|
| return PROCESS_NONE;
|
| }
|
|
|
| if (hostname.empty()) {
|
| // Invalid lockfile.
|
| - UnlinkPath(lock_path_.value());
|
| + UnlinkPath(lock_path_);
|
| return PROCESS_NONE;
|
| }
|
|
|
| @@ -813,20 +800,20 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
|
|
|
| if (!IsChromeProcess(pid)) {
|
| // Orphaned lockfile (no process with pid, or non-chrome process.)
|
| - UnlinkPath(lock_path_.value());
|
| + UnlinkPath(lock_path_);
|
| return PROCESS_NONE;
|
| }
|
|
|
| if (IsSameChromeInstance(pid)) {
|
| // Orphaned lockfile (pid is part of same chrome instance we are, even
|
| // though we haven't tried to create a lockfile yet).
|
| - UnlinkPath(lock_path_.value());
|
| + UnlinkPath(lock_path_);
|
| return PROCESS_NONE;
|
| }
|
|
|
| if (retries == timeout_seconds) {
|
| // Retries failed. Kill the unresponsive chrome process and continue.
|
| - if (!kill_unresponsive || !KillProcessByLockPath(lock_path_.value()))
|
| + if (!kill_unresponsive || !KillProcessByLockPath(lock_path_))
|
| return PROFILE_IN_USE;
|
| return PROCESS_NONE;
|
| }
|
| @@ -857,7 +844,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
|
| // Send the message
|
| if (!WriteToSocket(socket.fd(), to_send.data(), to_send.length())) {
|
| // Try to kill the other process, because it might have been dead.
|
| - if (!kill_unresponsive || !KillProcessByLockPath(lock_path_.value()))
|
| + if (!kill_unresponsive || !KillProcessByLockPath(lock_path_))
|
| return PROFILE_IN_USE;
|
| return PROCESS_NONE;
|
| }
|
| @@ -873,7 +860,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
|
|
|
| // Failed to read ACK, the other process might have been frozen.
|
| if (len <= 0) {
|
| - if (!kill_unresponsive || !KillProcessByLockPath(lock_path_.value()))
|
| + if (!kill_unresponsive || !KillProcessByLockPath(lock_path_))
|
| return PROFILE_IN_USE;
|
| return PROCESS_NONE;
|
| }
|
| @@ -928,15 +915,15 @@ bool ProcessSingleton::Create() {
|
|
|
| // The symlink lock is pointed to the hostname and process id, so other
|
| // processes can find it out.
|
| - std::string symlink_content = StringPrintf(
|
| + FilePath symlink_content(StringPrintf(
|
| "%s%c%u",
|
| net::GetHostName().c_str(),
|
| kLockDelimiter,
|
| - base::GetCurrentProcId());
|
| + base::GetCurrentProcId()));
|
|
|
| // Create symbol link before binding the socket, to ensure only one instance
|
| // can have the socket open.
|
| - if (!SymlinkPath(symlink_content, lock_path_.value())) {
|
| + if (!SymlinkPath(symlink_content, lock_path_)) {
|
| // If we failed to create the lock, most likely another instance won the
|
| // startup race.
|
| return false;
|
| @@ -952,14 +939,14 @@ bool ProcessSingleton::Create() {
|
| // Setup the socket symlink and the two cookies.
|
| FilePath socket_target_path =
|
| socket_dir_.path().Append(chrome::kSingletonSocketFilename);
|
| - std::string cookie = GenerateCookie();
|
| + FilePath cookie(GenerateCookie());
|
| FilePath remote_cookie_path =
|
| socket_dir_.path().Append(chrome::kSingletonCookieFilename);
|
| - UnlinkPath(socket_path_.value());
|
| - UnlinkPath(cookie_path_.value());
|
| - if (!SymlinkPath(socket_target_path.value(), socket_path_.value()) ||
|
| - !SymlinkPath(cookie, cookie_path_.value()) ||
|
| - !SymlinkPath(cookie, remote_cookie_path.value())) {
|
| + UnlinkPath(socket_path_);
|
| + UnlinkPath(cookie_path_);
|
| + if (!SymlinkPath(socket_target_path, socket_path_) ||
|
| + !SymlinkPath(cookie, cookie_path_) ||
|
| + !SymlinkPath(cookie, remote_cookie_path)) {
|
| // We've already locked things, so we can't have lost the startup race,
|
| // but something doesn't like us.
|
| LOG(ERROR) << "Failed to create symlinks.";
|
| @@ -992,7 +979,7 @@ bool ProcessSingleton::Create() {
|
| }
|
|
|
| void ProcessSingleton::Cleanup() {
|
| - UnlinkPath(socket_path_.value());
|
| - UnlinkPath(cookie_path_.value());
|
| - UnlinkPath(lock_path_.value());
|
| + UnlinkPath(socket_path_);
|
| + UnlinkPath(cookie_path_);
|
| + UnlinkPath(lock_path_);
|
| }
|
|
|