Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(579)

Side by Side Diff: chrome/browser/process_singleton_posix.cc

Issue 2871793003: Added histograms on process singleton create when remote process exists and we cannot notify it (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 758 matching lines...) Expand 10 before | Expand all | Expand 10 after
769 std::string hostname; 769 std::string hostname;
770 int pid; 770 int pid;
771 if (!ParseLockPath(lock_path_, &hostname, &pid)) { 771 if (!ParseLockPath(lock_path_, &hostname, &pid)) {
772 // No lockfile exists. 772 // No lockfile exists.
773 return PROCESS_NONE; 773 return PROCESS_NONE;
774 } 774 }
775 775
776 if (hostname.empty()) { 776 if (hostname.empty()) {
777 // Invalid lockfile. 777 // Invalid lockfile.
778 UnlinkPath(lock_path_); 778 UnlinkPath(lock_path_);
779 UMA_HISTOGRAM_ENUMERATION(
780 "Chrome.ProcessSingleton.RemoteProcessInteractionResult",
781 INVALID_LOCK_FILE, MAX_HUNG_REMOTE_PROCESS_ACTION);
gab 2017/05/10 15:16:50 Each UMA macro expands to a fair amount of code. E
Alexey Seren 2017/05/11 13:42:05 Acknowledged.
779 return PROCESS_NONE; 782 return PROCESS_NONE;
780 } 783 }
781 784
782 if (hostname != net::GetHostName() && !IsChromeProcess(pid)) { 785 if (hostname != net::GetHostName() && !IsChromeProcess(pid)) {
783 // Locked by process on another host. If the user selected to unlock 786 // Locked by process on another host. If the user selected to unlock
784 // the profile, try to continue; otherwise quit. 787 // the profile, try to continue; otherwise quit.
785 if (DisplayProfileInUseError(lock_path_, hostname, pid)) { 788 if (DisplayProfileInUseError(lock_path_, hostname, pid)) {
786 UnlinkPath(lock_path_); 789 UnlinkPath(lock_path_);
790 UMA_HISTOGRAM_ENUMERATION(
791 "Chrome.ProcessSingleton.RemoteProcessInteractionResult",
792 PROFILE_UNLOCKED, MAX_HUNG_REMOTE_PROCESS_ACTION);
787 return PROCESS_NONE; 793 return PROCESS_NONE;
788 } 794 }
789 return PROFILE_IN_USE; 795 return PROFILE_IN_USE;
790 } 796 }
791 797
792 if (!IsChromeProcess(pid)) { 798 if (!IsChromeProcess(pid)) {
793 // Orphaned lockfile (no process with pid, or non-chrome process.) 799 // Orphaned lockfile (no process with pid, or non-chrome process.)
800 UMA_HISTOGRAM_ENUMERATION(
801 "Chrome.ProcessSingleton.RemoteProcessInteractionResult",
802 ORPHANED_LOCK_FILE, MAX_HUNG_REMOTE_PROCESS_ACTION);
gab 2017/05/10 15:16:50 To be consistent I'd say have the UMA logging alwa
Alexey Seren 2017/05/11 13:42:05 Acknowledged.
794 UnlinkPath(lock_path_); 803 UnlinkPath(lock_path_);
795 return PROCESS_NONE; 804 return PROCESS_NONE;
796 } 805 }
797 806
798 if (IsSameChromeInstance(pid)) { 807 if (IsSameChromeInstance(pid)) {
799 // 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
800 // though we haven't tried to create a lockfile yet). 809 // though we haven't tried to create a lockfile yet).
801 UnlinkPath(lock_path_); 810 UnlinkPath(lock_path_);
811 UMA_HISTOGRAM_ENUMERATION(
812 "Chrome.ProcessSingleton.RemoteProcessInteractionResult",
813 SAME_BROWSER_INSTANCE, MAX_HUNG_REMOTE_PROCESS_ACTION);
802 return PROCESS_NONE; 814 return PROCESS_NONE;
803 } 815 }
804 816
805 if (retries == retry_attempts) { 817 if (retries == retry_attempts) {
818 if (kill_unresponsive) {
819 UMA_HISTOGRAM_ENUMERATION(
820 "Chrome.ProcessSingleton.RemoteHungProcessTerminateReason",
821 NOTIFY_ATTEMPTS_EXCEEDED, MAX_REMOTE_HUNG_PROCESS_TERMINATE_REASON);
gab 2017/05/10 15:16:50 Same here, instead of if (kill_unresponsive) {}, m
Alexey Seren 2017/05/11 13:42:05 Acknowledged.
822 }
806 // Retries failed. Kill the unresponsive chrome process and continue. 823 // Retries failed. Kill the unresponsive chrome process and continue.
807 if (!kill_unresponsive || !KillProcessByLockPath()) 824 if (!kill_unresponsive || !KillProcessByLockPath())
808 return PROFILE_IN_USE; 825 return PROFILE_IN_USE;
809 return PROCESS_NONE; 826 return PROCESS_NONE;
810 } 827 }
811 828
812 base::PlatformThread::Sleep(sleep_interval); 829 base::PlatformThread::Sleep(sleep_interval);
813 } 830 }
814 831
815 timeval socket_timeout = TimeDeltaToTimeVal(timeout); 832 timeval socket_timeout = TimeDeltaToTimeVal(timeout);
(...skipping 15 matching lines...) Expand all
831 848
832 const std::vector<std::string>& argv = cmd_line.argv(); 849 const std::vector<std::string>& argv = cmd_line.argv();
833 for (std::vector<std::string>::const_iterator it = argv.begin(); 850 for (std::vector<std::string>::const_iterator it = argv.begin();
834 it != argv.end(); ++it) { 851 it != argv.end(); ++it) {
835 to_send.push_back(kTokenDelimiter); 852 to_send.push_back(kTokenDelimiter);
836 to_send.append(*it); 853 to_send.append(*it);
837 } 854 }
838 855
839 // Send the message 856 // Send the message
840 if (!WriteToSocket(socket.fd(), to_send.data(), to_send.length())) { 857 if (!WriteToSocket(socket.fd(), to_send.data(), to_send.length())) {
858 if (kill_unresponsive) {
859 UMA_HISTOGRAM_ENUMERATION(
860 "Chrome.ProcessSingleton.RemoteHungProcessTerminateReason",
861 SOCKET_WRITE_FAILED, MAX_REMOTE_HUNG_PROCESS_TERMINATE_REASON);
862 }
841 // Try to kill the other process, because it might have been dead. 863 // Try to kill the other process, because it might have been dead.
842 if (!kill_unresponsive || !KillProcessByLockPath()) 864 if (!kill_unresponsive || !KillProcessByLockPath())
843 return PROFILE_IN_USE; 865 return PROFILE_IN_USE;
844 return PROCESS_NONE; 866 return PROCESS_NONE;
845 } 867 }
846 868
847 if (shutdown(socket.fd(), SHUT_WR) < 0) 869 if (shutdown(socket.fd(), SHUT_WR) < 0)
848 PLOG(ERROR) << "shutdown() failed"; 870 PLOG(ERROR) << "shutdown() failed";
849 871
850 // Read ACK message from the other process. It might be blocked for a certain 872 // Read ACK message from the other process. It might be blocked for a certain
851 // timeout, to make sure the other process has enough time to return ACK. 873 // timeout, to make sure the other process has enough time to return ACK.
852 char buf[kMaxACKMessageLength + 1]; 874 char buf[kMaxACKMessageLength + 1];
853 ssize_t len = ReadFromSocket(socket.fd(), buf, kMaxACKMessageLength, timeout); 875 ssize_t len = ReadFromSocket(socket.fd(), buf, kMaxACKMessageLength, timeout);
854 876
855 // Failed to read ACK, the other process might have been frozen. 877 // Failed to read ACK, the other process might have been frozen.
856 if (len <= 0) { 878 if (len <= 0) {
879 if (kill_unresponsive) {
880 UMA_HISTOGRAM_ENUMERATION(
881 "Chrome.ProcessSingleton.RemoteHungProcessTerminateReason",
882 SOCKET_READ_FAILED, MAX_REMOTE_HUNG_PROCESS_TERMINATE_REASON);
883 }
857 if (!kill_unresponsive || !KillProcessByLockPath()) 884 if (!kill_unresponsive || !KillProcessByLockPath())
858 return PROFILE_IN_USE; 885 return PROFILE_IN_USE;
859 return PROCESS_NONE; 886 return PROCESS_NONE;
860 } 887 }
861 888
862 buf[len] = '\0'; 889 buf[len] = '\0';
863 if (strncmp(buf, kShutdownToken, arraysize(kShutdownToken) - 1) == 0) { 890 if (strncmp(buf, kShutdownToken, arraysize(kShutdownToken) - 1) == 0) {
864 // The other process is shutting down, it's safe to start a new process. 891 // The other process is shutting down, it's safe to start a new process.
892 UMA_HISTOGRAM_ENUMERATION(
893 "Chrome.ProcessSingleton.RemoteProcessInteractionResult",
894 REMOTE_PROCESS_SHUTTING_DOWN, MAX_HUNG_REMOTE_PROCESS_ACTION);
865 return PROCESS_NONE; 895 return PROCESS_NONE;
866 } else if (strncmp(buf, kACKToken, arraysize(kACKToken) - 1) == 0) { 896 } else if (strncmp(buf, kACKToken, arraysize(kACKToken) - 1) == 0) {
867 #if defined(TOOLKIT_VIEWS) && defined(OS_LINUX) && !defined(OS_CHROMEOS) 897 #if defined(TOOLKIT_VIEWS) && defined(OS_LINUX) && !defined(OS_CHROMEOS)
868 // Likely NULL in unit tests. 898 // Likely NULL in unit tests.
869 views::LinuxUI* linux_ui = views::LinuxUI::instance(); 899 views::LinuxUI* linux_ui = views::LinuxUI::instance();
870 if (linux_ui) 900 if (linux_ui)
871 linux_ui->NotifyWindowManagerStartupComplete(); 901 linux_ui->NotifyWindowManagerStartupComplete();
872 #endif 902 #endif
873 903
874 // Assume the other process is handling the request. 904 // Assume the other process is handling the request.
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 } 1080 }
1051 return true; 1081 return true;
1052 } 1082 }
1053 1083
1054 bool ProcessSingleton::KillProcessByLockPath() { 1084 bool ProcessSingleton::KillProcessByLockPath() {
1055 std::string hostname; 1085 std::string hostname;
1056 int pid; 1086 int pid;
1057 ParseLockPath(lock_path_, &hostname, &pid); 1087 ParseLockPath(lock_path_, &hostname, &pid);
1058 1088
1059 if (!hostname.empty() && hostname != net::GetHostName()) { 1089 if (!hostname.empty() && hostname != net::GetHostName()) {
1060 return DisplayProfileInUseError(lock_path_, hostname, pid); 1090 bool res = DisplayProfileInUseError(lock_path_, hostname, pid);
1091 if (res) {
1092 UnlinkPath(lock_path_);
Alexey Seren 2017/05/10 04:27:07 We need to unlink lock file if user selects to unl
gab 2017/05/10 15:16:50 Is this a bug fix? If so, should go in a separate
Alexey Seren 2017/05/11 13:42:05 Yes it is a bug fix. I will move it to separate CL
1093 UMA_HISTOGRAM_ENUMERATION(
1094 "Chrome.ProcessSingleton.RemoteProcessInteractionResult",
1095 PROFILE_UNLOCKED, MAX_HUNG_REMOTE_PROCESS_ACTION);
1096 }
1097 return res;
1061 } 1098 }
1062 UnlinkPath(lock_path_); 1099 UnlinkPath(lock_path_);
1063 1100
1064 if (IsSameChromeInstance(pid)) 1101 if (IsSameChromeInstance(pid)) {
1102 UMA_HISTOGRAM_ENUMERATION(
1103 "Chrome.ProcessSingleton.RemoteProcessInteractionResult",
1104 SAME_BROWSER_INSTANCE, MAX_HUNG_REMOTE_PROCESS_ACTION);
1065 return true; 1105 return true;
1106 }
1066 1107
1067 if (pid > 0) { 1108 if (pid > 0) {
1068 kill_callback_.Run(pid); 1109 kill_callback_.Run(pid);
1069 return true; 1110 return true;
1070 } 1111 }
1071 1112
1113 UMA_HISTOGRAM_ENUMERATION(
1114 "Chrome.ProcessSingleton.RemoteProcessInteractionResult",
1115 FAILED_TO_EXTRACT_PID, MAX_HUNG_REMOTE_PROCESS_ACTION);
1116
1072 LOG(ERROR) << "Failed to extract pid from path: " << lock_path_.value(); 1117 LOG(ERROR) << "Failed to extract pid from path: " << lock_path_.value();
1073 return true; 1118 return true;
1074 } 1119 }
1075 1120
1076 void ProcessSingleton::KillProcess(int pid) { 1121 void ProcessSingleton::KillProcess(int pid) {
1077 // TODO(james.su@gmail.com): Is SIGKILL ok? 1122 // TODO(james.su@gmail.com): Is SIGKILL ok?
1078 int rv = kill(static_cast<base::ProcessHandle>(pid), SIGKILL); 1123 int rv = kill(static_cast<base::ProcessHandle>(pid), SIGKILL);
1079 // ESRCH = No Such Process (can happen if the other process is already in 1124 // ESRCH = No Such Process (can happen if the other process is already in
1080 // progress of shutting down and finishes before we try to kill it). 1125 // progress of shutting down and finishes before we try to kill it).
1081 DCHECK(rv == 0 || errno == ESRCH) << "Error killing process: " 1126 DCHECK(rv == 0 || errno == ESRCH) << "Error killing process: "
1082 << base::safe_strerror(errno); 1127 << base::safe_strerror(errno);
1128
1129 int error_code = (rv == 0) ? 0 : errno;
1130 UMA_HISTOGRAM_SPARSE_SLOWLY(
1131 "Chrome.ProcessSingleton.TerminateProcessErrorCode.Posix", error_code);
1132
1133 RemoteProcessInteractionResult action = TERMINATE_SUCCEEDED;
1134 if (rv != 0) {
1135 switch (error_code) {
1136 case ESRCH:
1137 action = REMOTE_PROCESS_NOT_FOUND;
1138 break;
1139 case EPERM:
1140 action = TERMINATE_NOT_ENOUGH_PERMISSIONS;
1141 break;
1142 default: { action = TERMINATE_FAILED; }
gab 2017/05/10 15:16:50 use same syntax as other cases for default, i.e.
Alexey Seren 2017/05/11 13:42:05 Acknowledged.
1143 }
1144 }
1145 UMA_HISTOGRAM_ENUMERATION(
1146 "Chrome.ProcessSingleton.RemoteProcessInteractionResult", action,
1147 MAX_HUNG_REMOTE_PROCESS_ACTION);
1083 } 1148 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698