| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // On Linux, when the user tries to launch a second copy of chrome, we check | 5 // On Linux, when the user tries to launch a second copy of chrome, we check |
| 6 // for a socket in the user's profile directory. If the socket file is open we | 6 // for a socket in the user's profile directory. If the socket file is open we |
| 7 // send a message to the first chrome browser process with the current | 7 // send a message to the first chrome browser process with the current |
| 8 // directory and second process command line flags. The second process then | 8 // directory and second process command line flags. The second process then |
| 9 // exits. | 9 // exits. |
| 10 // | 10 // |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 #include <cstring> | 53 #include <cstring> |
| 54 #include <set> | 54 #include <set> |
| 55 #include <string> | 55 #include <string> |
| 56 | 56 |
| 57 #include "app/l10n_util.h" | 57 #include "app/l10n_util.h" |
| 58 #include "base/base_paths.h" | 58 #include "base/base_paths.h" |
| 59 #include "base/basictypes.h" | 59 #include "base/basictypes.h" |
| 60 #include "base/command_line.h" | 60 #include "base/command_line.h" |
| 61 #include "base/eintr_wrapper.h" | 61 #include "base/eintr_wrapper.h" |
| 62 #include "base/file_path.h" | 62 #include "base/file_path.h" |
| 63 #include "base/file_util.h" |
| 63 #include "base/logging.h" | 64 #include "base/logging.h" |
| 64 #include "base/message_loop.h" | 65 #include "base/message_loop.h" |
| 65 #include "base/path_service.h" | 66 #include "base/path_service.h" |
| 66 #include "base/platform_thread.h" | 67 #include "base/platform_thread.h" |
| 67 #include "base/process_util.h" | 68 #include "base/process_util.h" |
| 68 #include "base/rand_util.h" | 69 #include "base/rand_util.h" |
| 69 #include "base/safe_strerror_posix.h" | 70 #include "base/safe_strerror_posix.h" |
| 70 #include "base/stl_util-inl.h" | 71 #include "base/stl_util-inl.h" |
| 71 #include "base/string_number_conversions.h" | 72 #include "base/string_number_conversions.h" |
| 72 #include "base/string_split.h" | 73 #include "base/string_split.h" |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 | 223 |
| 223 return sock; | 224 return sock; |
| 224 } | 225 } |
| 225 | 226 |
| 226 // Set up a socket and sockaddr appropriate for messaging. | 227 // Set up a socket and sockaddr appropriate for messaging. |
| 227 void SetupSocket(const std::string& path, int* sock, struct sockaddr_un* addr) { | 228 void SetupSocket(const std::string& path, int* sock, struct sockaddr_un* addr) { |
| 228 *sock = SetupSocketOnly(); | 229 *sock = SetupSocketOnly(); |
| 229 SetupSockAddr(path, addr); | 230 SetupSockAddr(path, addr); |
| 230 } | 231 } |
| 231 | 232 |
| 232 // Read a symbolic link, return empty string if given path is not a | |
| 233 // symbol link. This version does not interpret the errno, leaving | |
| 234 // the caller to do so. | |
| 235 bool ReadLinkSilent(const std::string& path, std::string* output) { | |
| 236 char buf[PATH_MAX]; | |
| 237 ssize_t len = readlink(path.c_str(), buf, PATH_MAX); | |
| 238 if (len >= 0) { | |
| 239 output->assign(buf, len); | |
| 240 return true; | |
| 241 } | |
| 242 output->clear(); | |
| 243 return false; | |
| 244 } | |
| 245 | |
| 246 // Read a symbolic link, return empty string if given path is not a symbol link. | 233 // Read a symbolic link, return empty string if given path is not a symbol link. |
| 247 std::string ReadLink(const std::string& path) { | 234 FilePath ReadLink(const FilePath& path) { |
| 248 std::string target; | 235 FilePath target; |
| 249 if (!ReadLinkSilent(path, &target)) { | 236 if (!file_util::ReadSymbolicLink(path, &target)) { |
| 250 // The only errno that should occur is ENOENT. | 237 // The only errno that should occur is ENOENT. |
| 251 if (errno != 0 && errno != ENOENT) | 238 if (errno != 0 && errno != ENOENT) |
| 252 PLOG(ERROR) << "readlink(" << path << ") failed"; | 239 PLOG(ERROR) << "readlink(" << path.value() << ") failed"; |
| 253 } | 240 } |
| 254 return target; | 241 return target; |
| 255 } | 242 } |
| 256 | 243 |
| 257 // Unlink a path. Return true on success. | 244 // Unlink a path. Return true on success. |
| 258 bool UnlinkPath(const std::string& path) { | 245 bool UnlinkPath(const FilePath& path) { |
| 259 int rv = unlink(path.c_str()); | 246 int rv = unlink(path.value().c_str()); |
| 260 if (rv < 0 && errno != ENOENT) | 247 if (rv < 0 && errno != ENOENT) |
| 261 PLOG(ERROR) << "Failed to unlink " << path; | 248 PLOG(ERROR) << "Failed to unlink " << path.value(); |
| 262 | 249 |
| 263 return rv == 0; | 250 return rv == 0; |
| 264 } | 251 } |
| 265 | 252 |
| 266 // Create a symlink. Returns true on success. | 253 // Create a symlink. Returns true on success. |
| 267 bool SymlinkPath(const std::string& target, const std::string& path) { | 254 bool SymlinkPath(const FilePath& target, const FilePath& path) { |
| 268 if (symlink(target.c_str(), path.c_str()) < 0) { | 255 if (!file_util::CreateSymbolicLink(target, path)) { |
| 269 // Double check the value in case symlink suceeded but we got an incorrect | 256 // Double check the value in case symlink suceeded but we got an incorrect |
| 270 // failure due to NFS packet loss & retry. | 257 // failure due to NFS packet loss & retry. |
| 271 int saved_errno = errno; | 258 int saved_errno = errno; |
| 272 if (ReadLink(path) != target) { | 259 if (ReadLink(path) != target) { |
| 273 // If we failed to create the lock, most likely another instance won the | 260 // If we failed to create the lock, most likely another instance won the |
| 274 // startup race. | 261 // startup race. |
| 275 errno = saved_errno; | 262 errno = saved_errno; |
| 276 PLOG(ERROR) << "Failed to create " << path; | 263 PLOG(ERROR) << "Failed to create " << path.value(); |
| 277 return false; | 264 return false; |
| 278 } | 265 } |
| 279 } | 266 } |
| 280 return true; | 267 return true; |
| 281 } | 268 } |
| 282 | 269 |
| 283 // Extract the hostname and pid from the lock symlink. | 270 // Extract the hostname and pid from the lock symlink. |
| 284 // Returns true if the lock existed. | 271 // Returns true if the lock existed. |
| 285 bool ParseLockPath(const std::string& path, | 272 bool ParseLockPath(const FilePath& path, |
| 286 std::string* hostname, | 273 std::string* hostname, |
| 287 int* pid) { | 274 int* pid) { |
| 288 std::string real_path = ReadLink(path); | 275 std::string real_path = ReadLink(path).value(); |
| 289 if (real_path.empty()) | 276 if (real_path.empty()) |
| 290 return false; | 277 return false; |
| 291 | 278 |
| 292 std::string::size_type pos = real_path.rfind(kLockDelimiter); | 279 std::string::size_type pos = real_path.rfind(kLockDelimiter); |
| 293 | 280 |
| 294 // If the path is not a symbolic link, or doesn't contain what we expect, | 281 // If the path is not a symbolic link, or doesn't contain what we expect, |
| 295 // bail. | 282 // bail. |
| 296 if (pos == std::string::npos) { | 283 if (pos == std::string::npos) { |
| 297 *hostname = ""; | 284 *hostname = ""; |
| 298 *pid = -1; | 285 *pid = -1; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 return false; | 330 return false; |
| 344 } | 331 } |
| 345 return true; | 332 return true; |
| 346 } | 333 } |
| 347 | 334 |
| 348 // Extract the process's pid from a symbol link path and if it is on | 335 // Extract the process's pid from a symbol link path and if it is on |
| 349 // the same host, kill the process, unlink the lock file and return true. | 336 // the same host, kill the process, unlink the lock file and return true. |
| 350 // If the process is part of the same chrome instance, unlink the lock file and | 337 // If the process is part of the same chrome instance, unlink the lock file and |
| 351 // return true without killing it. | 338 // return true without killing it. |
| 352 // If the process is on a different host, return false. | 339 // If the process is on a different host, return false. |
| 353 bool KillProcessByLockPath(const std::string& path) { | 340 bool KillProcessByLockPath(const FilePath& path) { |
| 354 std::string hostname; | 341 std::string hostname; |
| 355 int pid; | 342 int pid; |
| 356 ParseLockPath(path, &hostname, &pid); | 343 ParseLockPath(path, &hostname, &pid); |
| 357 | 344 |
| 358 if (!hostname.empty() && hostname != net::GetHostName()) { | 345 if (!hostname.empty() && hostname != net::GetHostName()) { |
| 359 DisplayProfileInUseError(path, hostname, pid); | 346 DisplayProfileInUseError(path.value(), hostname, pid); |
| 360 return false; | 347 return false; |
| 361 } | 348 } |
| 362 UnlinkPath(path); | 349 UnlinkPath(path); |
| 363 | 350 |
| 364 if (IsSameChromeInstance(pid)) | 351 if (IsSameChromeInstance(pid)) |
| 365 return true; | 352 return true; |
| 366 | 353 |
| 367 if (pid > 0) { | 354 if (pid > 0) { |
| 368 // TODO(james.su@gmail.com): Is SIGKILL ok? | 355 // TODO(james.su@gmail.com): Is SIGKILL ok? |
| 369 int rv = kill(static_cast<base::ProcessHandle>(pid), SIGKILL); | 356 int rv = kill(static_cast<base::ProcessHandle>(pid), SIGKILL); |
| 370 // ESRCH = No Such Process (can happen if the other process is already in | 357 // ESRCH = No Such Process (can happen if the other process is already in |
| 371 // progress of shutting down and finishes before we try to kill it). | 358 // progress of shutting down and finishes before we try to kill it). |
| 372 DCHECK(rv == 0 || errno == ESRCH) << "Error killing process: " | 359 DCHECK(rv == 0 || errno == ESRCH) << "Error killing process: " |
| 373 << safe_strerror(errno); | 360 << safe_strerror(errno); |
| 374 return true; | 361 return true; |
| 375 } | 362 } |
| 376 | 363 |
| 377 LOG(ERROR) << "Failed to extract pid from path: " << path; | 364 LOG(ERROR) << "Failed to extract pid from path: " << path.value(); |
| 378 return true; | 365 return true; |
| 379 } | 366 } |
| 380 | 367 |
| 381 // A helper class to hold onto a socket. | 368 // A helper class to hold onto a socket. |
| 382 class ScopedSocket { | 369 class ScopedSocket { |
| 383 public: | 370 public: |
| 384 ScopedSocket() : fd_(-1) { Reset(); } | 371 ScopedSocket() : fd_(-1) { Reset(); } |
| 385 ~ScopedSocket() { Close(); } | 372 ~ScopedSocket() { Close(); } |
| 386 int fd() { return fd_; } | 373 int fd() { return fd_; } |
| 387 void Reset() { | 374 void Reset() { |
| 388 Close(); | 375 Close(); |
| 389 fd_ = SetupSocketOnly(); | 376 fd_ = SetupSocketOnly(); |
| 390 } | 377 } |
| 391 void Close() { | 378 void Close() { |
| 392 if (fd_ >= 0) | 379 if (fd_ >= 0) |
| 393 CloseSocket(fd_); | 380 CloseSocket(fd_); |
| 394 fd_ = -1; | 381 fd_ = -1; |
| 395 } | 382 } |
| 396 private: | 383 private: |
| 397 int fd_; | 384 int fd_; |
| 398 }; | 385 }; |
| 399 | 386 |
| 400 // Returns a random string for uniquifying profile connections. | 387 // Returns a random string for uniquifying profile connections. |
| 401 std::string GenerateCookie() { | 388 std::string GenerateCookie() { |
| 402 return base::Uint64ToString(base::RandUint64()); | 389 return base::Uint64ToString(base::RandUint64()); |
| 403 } | 390 } |
| 404 | 391 |
| 405 bool CheckCookie(const FilePath& path, const std::string& cookie) { | 392 bool CheckCookie(const FilePath& path, const FilePath& cookie) { |
| 406 return (cookie == ReadLink(path.value())); | 393 return (cookie == ReadLink(path)); |
| 407 } | 394 } |
| 408 | 395 |
| 409 bool ConnectSocket(ScopedSocket* socket, | 396 bool ConnectSocket(ScopedSocket* socket, |
| 410 const FilePath& socket_path, | 397 const FilePath& socket_path, |
| 411 const FilePath& cookie_path) { | 398 const FilePath& cookie_path) { |
| 412 std::string socket_target; | 399 FilePath socket_target; |
| 413 if (ReadLinkSilent(socket_path.value(), &socket_target)) { | 400 if (file_util::ReadSymbolicLink(socket_path, &socket_target)) { |
| 414 // It's a symlink. Read the cookie. | 401 // It's a symlink. Read the cookie. |
| 415 std::string cookie = ReadLink(cookie_path.value()); | 402 FilePath cookie = ReadLink(cookie_path); |
| 416 if (cookie.empty()) | 403 if (cookie.empty()) |
| 417 return false; | 404 return false; |
| 418 FilePath remote_cookie = FilePath(socket_target).DirName(). | 405 FilePath remote_cookie = socket_target.DirName(). |
| 419 Append(chrome::kSingletonCookieFilename); | 406 Append(chrome::kSingletonCookieFilename); |
| 420 // Verify the cookie before connecting. | 407 // Verify the cookie before connecting. |
| 421 if (!CheckCookie(remote_cookie, cookie)) | 408 if (!CheckCookie(remote_cookie, cookie)) |
| 422 return false; | 409 return false; |
| 423 // Now we know the directory was (at that point) created by the profile | 410 // Now we know the directory was (at that point) created by the profile |
| 424 // owner. Try to connect. | 411 // owner. Try to connect. |
| 425 sockaddr_un addr; | 412 sockaddr_un addr; |
| 426 SetupSockAddr(socket_path.value(), &addr); | 413 SetupSockAddr(socket_path.value(), &addr); |
| 427 int ret = HANDLE_EINTR(connect(socket->fd(), | 414 int ret = HANDLE_EINTR(connect(socket->fd(), |
| 428 reinterpret_cast<sockaddr*>(&addr), | 415 reinterpret_cast<sockaddr*>(&addr), |
| 429 sizeof(addr))); | 416 sizeof(addr))); |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 787 if (ConnectSocket(&socket, socket_path_, cookie_path_)) | 774 if (ConnectSocket(&socket, socket_path_, cookie_path_)) |
| 788 break; | 775 break; |
| 789 | 776 |
| 790 // If we're in a race with another process, they may be in Create() and have | 777 // If we're in a race with another process, they may be in Create() and have |
| 791 // created the lock but not attached to the socket. So we check if the | 778 // created the lock but not attached to the socket. So we check if the |
| 792 // process with the pid from the lockfile is currently running and is a | 779 // process with the pid from the lockfile is currently running and is a |
| 793 // chrome browser. If so, we loop and try again for |timeout_seconds|. | 780 // chrome browser. If so, we loop and try again for |timeout_seconds|. |
| 794 | 781 |
| 795 std::string hostname; | 782 std::string hostname; |
| 796 int pid; | 783 int pid; |
| 797 if (!ParseLockPath(lock_path_.value(), &hostname, &pid)) { | 784 if (!ParseLockPath(lock_path_, &hostname, &pid)) { |
| 798 // No lockfile exists. | 785 // No lockfile exists. |
| 799 return PROCESS_NONE; | 786 return PROCESS_NONE; |
| 800 } | 787 } |
| 801 | 788 |
| 802 if (hostname.empty()) { | 789 if (hostname.empty()) { |
| 803 // Invalid lockfile. | 790 // Invalid lockfile. |
| 804 UnlinkPath(lock_path_.value()); | 791 UnlinkPath(lock_path_); |
| 805 return PROCESS_NONE; | 792 return PROCESS_NONE; |
| 806 } | 793 } |
| 807 | 794 |
| 808 if (hostname != net::GetHostName()) { | 795 if (hostname != net::GetHostName()) { |
| 809 // Locked by process on another host. | 796 // Locked by process on another host. |
| 810 DisplayProfileInUseError(lock_path_.value(), hostname, pid); | 797 DisplayProfileInUseError(lock_path_.value(), hostname, pid); |
| 811 return PROFILE_IN_USE; | 798 return PROFILE_IN_USE; |
| 812 } | 799 } |
| 813 | 800 |
| 814 if (!IsChromeProcess(pid)) { | 801 if (!IsChromeProcess(pid)) { |
| 815 // Orphaned lockfile (no process with pid, or non-chrome process.) | 802 // Orphaned lockfile (no process with pid, or non-chrome process.) |
| 816 UnlinkPath(lock_path_.value()); | 803 UnlinkPath(lock_path_); |
| 817 return PROCESS_NONE; | 804 return PROCESS_NONE; |
| 818 } | 805 } |
| 819 | 806 |
| 820 if (IsSameChromeInstance(pid)) { | 807 if (IsSameChromeInstance(pid)) { |
| 821 // Orphaned lockfile (pid is part of same chrome instance we are, even | 808 // Orphaned lockfile (pid is part of same chrome instance we are, even |
| 822 // though we haven't tried to create a lockfile yet). | 809 // though we haven't tried to create a lockfile yet). |
| 823 UnlinkPath(lock_path_.value()); | 810 UnlinkPath(lock_path_); |
| 824 return PROCESS_NONE; | 811 return PROCESS_NONE; |
| 825 } | 812 } |
| 826 | 813 |
| 827 if (retries == timeout_seconds) { | 814 if (retries == timeout_seconds) { |
| 828 // Retries failed. Kill the unresponsive chrome process and continue. | 815 // Retries failed. Kill the unresponsive chrome process and continue. |
| 829 if (!kill_unresponsive || !KillProcessByLockPath(lock_path_.value())) | 816 if (!kill_unresponsive || !KillProcessByLockPath(lock_path_)) |
| 830 return PROFILE_IN_USE; | 817 return PROFILE_IN_USE; |
| 831 return PROCESS_NONE; | 818 return PROCESS_NONE; |
| 832 } | 819 } |
| 833 | 820 |
| 834 PlatformThread::Sleep(1000 /* ms */); | 821 PlatformThread::Sleep(1000 /* ms */); |
| 835 } | 822 } |
| 836 | 823 |
| 837 timeval timeout = {timeout_seconds, 0}; | 824 timeval timeout = {timeout_seconds, 0}; |
| 838 setsockopt(socket.fd(), SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); | 825 setsockopt(socket.fd(), SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); |
| 839 | 826 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 850 const std::vector<std::string>& argv = cmd_line.argv(); | 837 const std::vector<std::string>& argv = cmd_line.argv(); |
| 851 for (std::vector<std::string>::const_iterator it = argv.begin(); | 838 for (std::vector<std::string>::const_iterator it = argv.begin(); |
| 852 it != argv.end(); ++it) { | 839 it != argv.end(); ++it) { |
| 853 to_send.push_back(kTokenDelimiter); | 840 to_send.push_back(kTokenDelimiter); |
| 854 to_send.append(*it); | 841 to_send.append(*it); |
| 855 } | 842 } |
| 856 | 843 |
| 857 // Send the message | 844 // Send the message |
| 858 if (!WriteToSocket(socket.fd(), to_send.data(), to_send.length())) { | 845 if (!WriteToSocket(socket.fd(), to_send.data(), to_send.length())) { |
| 859 // Try to kill the other process, because it might have been dead. | 846 // Try to kill the other process, because it might have been dead. |
| 860 if (!kill_unresponsive || !KillProcessByLockPath(lock_path_.value())) | 847 if (!kill_unresponsive || !KillProcessByLockPath(lock_path_)) |
| 861 return PROFILE_IN_USE; | 848 return PROFILE_IN_USE; |
| 862 return PROCESS_NONE; | 849 return PROCESS_NONE; |
| 863 } | 850 } |
| 864 | 851 |
| 865 if (shutdown(socket.fd(), SHUT_WR) < 0) | 852 if (shutdown(socket.fd(), SHUT_WR) < 0) |
| 866 PLOG(ERROR) << "shutdown() failed"; | 853 PLOG(ERROR) << "shutdown() failed"; |
| 867 | 854 |
| 868 // Read ACK message from the other process. It might be blocked for a certain | 855 // Read ACK message from the other process. It might be blocked for a certain |
| 869 // timeout, to make sure the other process has enough time to return ACK. | 856 // timeout, to make sure the other process has enough time to return ACK. |
| 870 char buf[kMaxACKMessageLength + 1]; | 857 char buf[kMaxACKMessageLength + 1]; |
| 871 ssize_t len = | 858 ssize_t len = |
| 872 ReadFromSocket(socket.fd(), buf, kMaxACKMessageLength, timeout_seconds); | 859 ReadFromSocket(socket.fd(), buf, kMaxACKMessageLength, timeout_seconds); |
| 873 | 860 |
| 874 // Failed to read ACK, the other process might have been frozen. | 861 // Failed to read ACK, the other process might have been frozen. |
| 875 if (len <= 0) { | 862 if (len <= 0) { |
| 876 if (!kill_unresponsive || !KillProcessByLockPath(lock_path_.value())) | 863 if (!kill_unresponsive || !KillProcessByLockPath(lock_path_)) |
| 877 return PROFILE_IN_USE; | 864 return PROFILE_IN_USE; |
| 878 return PROCESS_NONE; | 865 return PROCESS_NONE; |
| 879 } | 866 } |
| 880 | 867 |
| 881 buf[len] = '\0'; | 868 buf[len] = '\0'; |
| 882 if (strncmp(buf, kShutdownToken, arraysize(kShutdownToken) - 1) == 0) { | 869 if (strncmp(buf, kShutdownToken, arraysize(kShutdownToken) - 1) == 0) { |
| 883 // The other process is shutting down, it's safe to start a new process. | 870 // The other process is shutting down, it's safe to start a new process. |
| 884 return PROCESS_NONE; | 871 return PROCESS_NONE; |
| 885 } else if (strncmp(buf, kACKToken, arraysize(kACKToken) - 1) == 0) { | 872 } else if (strncmp(buf, kACKToken, arraysize(kACKToken) - 1) == 0) { |
| 886 // Notify the window manager that we've started up; if we do not open a | 873 // Notify the window manager that we've started up; if we do not open a |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 921 | 908 |
| 922 return LOCK_ERROR; | 909 return LOCK_ERROR; |
| 923 } | 910 } |
| 924 | 911 |
| 925 bool ProcessSingleton::Create() { | 912 bool ProcessSingleton::Create() { |
| 926 int sock; | 913 int sock; |
| 927 sockaddr_un addr; | 914 sockaddr_un addr; |
| 928 | 915 |
| 929 // The symlink lock is pointed to the hostname and process id, so other | 916 // The symlink lock is pointed to the hostname and process id, so other |
| 930 // processes can find it out. | 917 // processes can find it out. |
| 931 std::string symlink_content = StringPrintf( | 918 FilePath symlink_content(StringPrintf( |
| 932 "%s%c%u", | 919 "%s%c%u", |
| 933 net::GetHostName().c_str(), | 920 net::GetHostName().c_str(), |
| 934 kLockDelimiter, | 921 kLockDelimiter, |
| 935 base::GetCurrentProcId()); | 922 base::GetCurrentProcId())); |
| 936 | 923 |
| 937 // Create symbol link before binding the socket, to ensure only one instance | 924 // Create symbol link before binding the socket, to ensure only one instance |
| 938 // can have the socket open. | 925 // can have the socket open. |
| 939 if (!SymlinkPath(symlink_content, lock_path_.value())) { | 926 if (!SymlinkPath(symlink_content, lock_path_)) { |
| 940 // If we failed to create the lock, most likely another instance won the | 927 // If we failed to create the lock, most likely another instance won the |
| 941 // startup race. | 928 // startup race. |
| 942 return false; | 929 return false; |
| 943 } | 930 } |
| 944 | 931 |
| 945 // Create the socket file somewhere in /tmp which is usually mounted as a | 932 // Create the socket file somewhere in /tmp which is usually mounted as a |
| 946 // normal filesystem. Some network filesystems (notably AFS) are screwy and | 933 // normal filesystem. Some network filesystems (notably AFS) are screwy and |
| 947 // do not support Unix domain sockets. | 934 // do not support Unix domain sockets. |
| 948 if (!socket_dir_.CreateUniqueTempDir()) { | 935 if (!socket_dir_.CreateUniqueTempDir()) { |
| 949 LOG(ERROR) << "Failed to create socket directory."; | 936 LOG(ERROR) << "Failed to create socket directory."; |
| 950 return false; | 937 return false; |
| 951 } | 938 } |
| 952 // Setup the socket symlink and the two cookies. | 939 // Setup the socket symlink and the two cookies. |
| 953 FilePath socket_target_path = | 940 FilePath socket_target_path = |
| 954 socket_dir_.path().Append(chrome::kSingletonSocketFilename); | 941 socket_dir_.path().Append(chrome::kSingletonSocketFilename); |
| 955 std::string cookie = GenerateCookie(); | 942 FilePath cookie(GenerateCookie()); |
| 956 FilePath remote_cookie_path = | 943 FilePath remote_cookie_path = |
| 957 socket_dir_.path().Append(chrome::kSingletonCookieFilename); | 944 socket_dir_.path().Append(chrome::kSingletonCookieFilename); |
| 958 UnlinkPath(socket_path_.value()); | 945 UnlinkPath(socket_path_); |
| 959 UnlinkPath(cookie_path_.value()); | 946 UnlinkPath(cookie_path_); |
| 960 if (!SymlinkPath(socket_target_path.value(), socket_path_.value()) || | 947 if (!SymlinkPath(socket_target_path, socket_path_) || |
| 961 !SymlinkPath(cookie, cookie_path_.value()) || | 948 !SymlinkPath(cookie, cookie_path_) || |
| 962 !SymlinkPath(cookie, remote_cookie_path.value())) { | 949 !SymlinkPath(cookie, remote_cookie_path)) { |
| 963 // We've already locked things, so we can't have lost the startup race, | 950 // We've already locked things, so we can't have lost the startup race, |
| 964 // but something doesn't like us. | 951 // but something doesn't like us. |
| 965 LOG(ERROR) << "Failed to create symlinks."; | 952 LOG(ERROR) << "Failed to create symlinks."; |
| 966 socket_dir_.Delete(); | 953 socket_dir_.Delete(); |
| 967 return false; | 954 return false; |
| 968 } | 955 } |
| 969 | 956 |
| 970 SetupSocket(socket_target_path.value(), &sock, &addr); | 957 SetupSocket(socket_target_path.value(), &sock, &addr); |
| 971 | 958 |
| 972 if (bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) { | 959 if (bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 985 DCHECK(ml); | 972 DCHECK(ml); |
| 986 ml->PostTask(FROM_HERE, NewRunnableMethod( | 973 ml->PostTask(FROM_HERE, NewRunnableMethod( |
| 987 watcher_.get(), | 974 watcher_.get(), |
| 988 &ProcessSingleton::LinuxWatcher::StartListening, | 975 &ProcessSingleton::LinuxWatcher::StartListening, |
| 989 sock)); | 976 sock)); |
| 990 | 977 |
| 991 return true; | 978 return true; |
| 992 } | 979 } |
| 993 | 980 |
| 994 void ProcessSingleton::Cleanup() { | 981 void ProcessSingleton::Cleanup() { |
| 995 UnlinkPath(socket_path_.value()); | 982 UnlinkPath(socket_path_); |
| 996 UnlinkPath(cookie_path_.value()); | 983 UnlinkPath(cookie_path_); |
| 997 UnlinkPath(lock_path_.value()); | 984 UnlinkPath(lock_path_); |
| 998 } | 985 } |
| OLD | NEW |