Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 620 foreground_window_(NULL), | 620 foreground_window_(NULL), |
| 621 ALLOW_THIS_IN_INITIALIZER_LIST(watcher_(new LinuxWatcher(this))) { | 621 ALLOW_THIS_IN_INITIALIZER_LIST(watcher_(new LinuxWatcher(this))) { |
| 622 socket_path_ = user_data_dir.Append(chrome::kSingletonSocketFilename); | 622 socket_path_ = user_data_dir.Append(chrome::kSingletonSocketFilename); |
| 623 lock_path_ = user_data_dir.Append(chrome::kSingletonLockFilename); | 623 lock_path_ = user_data_dir.Append(chrome::kSingletonLockFilename); |
| 624 } | 624 } |
| 625 | 625 |
| 626 ProcessSingleton::~ProcessSingleton() { | 626 ProcessSingleton::~ProcessSingleton() { |
| 627 } | 627 } |
| 628 | 628 |
| 629 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() { | 629 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() { |
| 630 return NotifyOtherProcessWithTimeout(kTimeoutInSeconds /* seconds */); | |
|
Paweł Hajdan Jr.
2009/09/17 19:45:56
nit: Is this /* seconds */ comment necessary? The
Evan Martin
2009/09/17 20:37:13
Good catch. It was leftover from before I had not
| |
| 631 } | |
| 632 | |
| 633 ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( | |
| 634 int timeout_seconds) { | |
| 630 int socket; | 635 int socket; |
| 631 sockaddr_un addr; | 636 sockaddr_un addr; |
| 632 SetupSocket(socket_path_.value(), &socket, &addr); | 637 SetupSocket(socket_path_.value(), &socket, &addr); |
| 633 | 638 |
| 634 // It'll close the socket automatically when exiting this method. | 639 // It'll close the socket automatically when exiting this method. |
| 635 SocketCloser socket_closer(socket); | 640 SocketCloser socket_closer(socket); |
| 636 | 641 |
| 637 // Connecting to the socket | 642 // Connecting to the socket |
| 638 int ret = HANDLE_EINTR(connect(socket, | 643 int ret = HANDLE_EINTR(connect(socket, |
| 639 reinterpret_cast<sockaddr*>(&addr), | 644 reinterpret_cast<sockaddr*>(&addr), |
| 640 sizeof(addr))); | 645 sizeof(addr))); |
| 641 if (ret < 0) { | 646 if (ret < 0) { |
| 642 // TODO(mattm): there is a bit of a race here if another instance on the | 647 // TODO(mattm): there is a bit of a race here if another instance on the |
| 643 // same host is in Create() and has created the lock but not attached to the | 648 // same host is in Create() and has created the lock but not attached to the |
| 644 // socket. Our CheckLockHostnameAndCleanup call will clean up their lock | 649 // socket. Our CheckLockHostnameAndCleanup call will clean up their lock |
| 645 // and allow us to create a new one. | 650 // and allow us to create a new one. |
| 646 if (!CheckLockHostnameAndCleanup(lock_path_.value())) | 651 if (!CheckLockHostnameAndCleanup(lock_path_.value())) |
| 647 return PROFILE_IN_USE; | 652 return PROFILE_IN_USE; |
| 648 return PROCESS_NONE; // Tell the caller there's nobody to notify. | 653 return PROCESS_NONE; // Tell the caller there's nobody to notify. |
| 649 } | 654 } |
| 650 | 655 |
| 651 timeval timeout = {20, 0}; | 656 timeval timeout = {timeout_seconds, 0}; |
| 652 setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); | 657 setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); |
| 653 | 658 |
| 654 // Found another process, prepare our command line | 659 // Found another process, prepare our command line |
| 655 // format is "START\0<current dir>\0<argv[0]>\0...\0<argv[n]>". | 660 // format is "START\0<current dir>\0<argv[0]>\0...\0<argv[n]>". |
| 656 std::string to_send(kStartToken); | 661 std::string to_send(kStartToken); |
| 657 to_send.push_back(kTokenDelimiter); | 662 to_send.push_back(kTokenDelimiter); |
| 658 | 663 |
| 659 FilePath current_dir; | 664 FilePath current_dir; |
| 660 if (!PathService::Get(base::DIR_CURRENT, ¤t_dir)) | 665 if (!PathService::Get(base::DIR_CURRENT, ¤t_dir)) |
| 661 return PROCESS_NONE; | 666 return PROCESS_NONE; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 677 return PROCESS_NONE; | 682 return PROCESS_NONE; |
| 678 } | 683 } |
| 679 | 684 |
| 680 if (shutdown(socket, SHUT_WR) < 0) | 685 if (shutdown(socket, SHUT_WR) < 0) |
| 681 LOG(ERROR) << "shutdown() failed: " << strerror(errno); | 686 LOG(ERROR) << "shutdown() failed: " << strerror(errno); |
| 682 | 687 |
| 683 // Read ACK message from the other process. It might be blocked for a certain | 688 // Read ACK message from the other process. It might be blocked for a certain |
| 684 // timeout, to make sure the other process has enough time to return ACK. | 689 // timeout, to make sure the other process has enough time to return ACK. |
| 685 char buf[kMaxACKMessageLength + 1]; | 690 char buf[kMaxACKMessageLength + 1]; |
| 686 ssize_t len = | 691 ssize_t len = |
| 687 ReadFromSocket(socket, buf, kMaxACKMessageLength, kTimeoutInSeconds); | 692 ReadFromSocket(socket, buf, kMaxACKMessageLength, timeout_seconds); |
| 688 | 693 |
| 689 // Failed to read ACK, the other process might have been frozen. | 694 // Failed to read ACK, the other process might have been frozen. |
| 690 if (len <= 0) { | 695 if (len <= 0) { |
| 691 if (!KillProcessByLockPath(lock_path_.value())) | 696 if (!KillProcessByLockPath(lock_path_.value())) |
| 692 return PROFILE_IN_USE; | 697 return PROFILE_IN_USE; |
| 693 return PROCESS_NONE; | 698 return PROCESS_NONE; |
| 694 } | 699 } |
| 695 | 700 |
| 696 buf[len] = '\0'; | 701 buf[len] = '\0'; |
| 697 if (strncmp(buf, kShutdownToken, arraysize(kShutdownToken) - 1) == 0) { | 702 if (strncmp(buf, kShutdownToken, arraysize(kShutdownToken) - 1) == 0) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 758 DCHECK(ml); | 763 DCHECK(ml); |
| 759 ml->PostTask(FROM_HERE, NewRunnableMethod( | 764 ml->PostTask(FROM_HERE, NewRunnableMethod( |
| 760 watcher_.get(), | 765 watcher_.get(), |
| 761 &ProcessSingleton::LinuxWatcher::StartListening, | 766 &ProcessSingleton::LinuxWatcher::StartListening, |
| 762 sock)); | 767 sock)); |
| 763 } | 768 } |
| 764 | 769 |
| 765 void ProcessSingleton::Cleanup() { | 770 void ProcessSingleton::Cleanup() { |
| 766 UnlinkPath(lock_path_.value()); | 771 UnlinkPath(lock_path_.value()); |
| 767 } | 772 } |
| OLD | NEW |