Chromium Code Reviews| Index: chrome/browser/process_singleton_posix.cc |
| diff --git a/chrome/browser/process_singleton_posix.cc b/chrome/browser/process_singleton_posix.cc |
| index f8786c67e6404c2678b65f8c0b16da815ce02d74..d487e36b1ba772e18eb459cbe502e463e2411555 100644 |
| --- a/chrome/browser/process_singleton_posix.cc |
| +++ b/chrome/browser/process_singleton_posix.cc |
| @@ -111,7 +111,8 @@ const int kTimeoutInSeconds = 20; |
| // Number of retries to notify the browser. 20 retries over 20 seconds = 1 try |
| // per second. |
| const int kRetryAttempts = 20; |
| -static bool g_disable_prompt; |
| +static bool g_disable_prompt = false; |
| +static bool g_skip_is_chrome_process_check = false; |
|
gab
2017/05/15 16:58:39
static and namespace{} are redundant, remove stati
Alexey Seren
2017/05/15 19:20:25
Acknowledged.
|
| const char kStartToken[] = "START"; |
| const char kACKToken[] = "ACK"; |
| const char kShutdownToken[] = "SHUTDOWN"; |
| @@ -338,8 +339,9 @@ bool DisplayProfileInUseError(const base::FilePath& lock_path, |
| bool IsChromeProcess(pid_t pid) { |
| base::FilePath other_chrome_path(base::GetProcessExecutablePath(pid)); |
| return (!other_chrome_path.empty() && |
| - other_chrome_path.BaseName() == |
| - base::FilePath(chrome::kBrowserProcessExecutableName)); |
| + (g_skip_is_chrome_process_check || |
|
Alexey Seren
2017/05/15 08:40:48
Do not check remote process name if g_skip_is_chro
|
| + other_chrome_path.BaseName() == |
| + base::FilePath(chrome::kBrowserProcessExecutableName))); |
| } |
| // A helper class to hold onto a socket. |
| @@ -464,6 +466,20 @@ bool ReplaceOldSingletonLock(const base::FilePath& symlink_content, |
| } |
| #endif // defined(OS_MACOSX) |
| +void SendRemoteProcessInteractionResultHistogram( |
| + ProcessSingleton::RemoteProcessInteractionResult result) { |
| + UMA_HISTOGRAM_ENUMERATION( |
| + "Chrome.ProcessSingleton.RemoteProcessInteractionResult", result, |
| + ProcessSingleton::REMOTE_PROCESS_INTERACTION_RESULT_COUNT); |
| +} |
| + |
| +void SendRemoteHungProcessTerminateReasonHistogram( |
| + ProcessSingleton::RemoteHungProcessTerminateReason reason) { |
| + UMA_HISTOGRAM_ENUMERATION( |
| + "Chrome.ProcessSingleton.RemoteHungProcessTerminateReason", reason, |
| + ProcessSingleton::REMOTE_HUNG_PROCESS_TERMINATE_REASON_COUNT); |
| +} |
| + |
| } // namespace |
| /////////////////////////////////////////////////////////////////////////////// |
| @@ -776,6 +792,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( |
| if (hostname.empty()) { |
| // Invalid lockfile. |
| UnlinkPath(lock_path_); |
| + SendRemoteProcessInteractionResultHistogram(INVALID_LOCK_FILE); |
| return PROCESS_NONE; |
| } |
| @@ -784,6 +801,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( |
| // the profile, try to continue; otherwise quit. |
| if (DisplayProfileInUseError(lock_path_, hostname, pid)) { |
| UnlinkPath(lock_path_); |
| + SendRemoteProcessInteractionResultHistogram(PROFILE_UNLOCKED); |
| return PROCESS_NONE; |
| } |
| return PROFILE_IN_USE; |
| @@ -792,6 +810,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( |
| if (!IsChromeProcess(pid)) { |
| // Orphaned lockfile (no process with pid, or non-chrome process.) |
| UnlinkPath(lock_path_); |
| + SendRemoteProcessInteractionResultHistogram(ORPHANED_LOCK_FILE); |
| return PROCESS_NONE; |
| } |
| @@ -799,6 +818,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( |
| // 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_); |
| + SendRemoteProcessInteractionResultHistogram(SAME_BROWSER_INSTANCE); |
| return PROCESS_NONE; |
| } |
| @@ -806,6 +826,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( |
| // Retries failed. Kill the unresponsive chrome process and continue. |
| if (!kill_unresponsive || !KillProcessByLockPath()) |
| return PROFILE_IN_USE; |
| + SendRemoteHungProcessTerminateReasonHistogram(NOTIFY_ATTEMPTS_EXCEEDED); |
| return PROCESS_NONE; |
| } |
| @@ -841,6 +862,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( |
| // Try to kill the other process, because it might have been dead. |
| if (!kill_unresponsive || !KillProcessByLockPath()) |
| return PROFILE_IN_USE; |
| + SendRemoteHungProcessTerminateReasonHistogram(SOCKET_WRITE_FAILED); |
| return PROCESS_NONE; |
| } |
| @@ -856,12 +878,14 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout( |
| if (len <= 0) { |
| if (!kill_unresponsive || !KillProcessByLockPath()) |
| return PROFILE_IN_USE; |
| + SendRemoteHungProcessTerminateReasonHistogram(SOCKET_READ_FAILED); |
| return PROCESS_NONE; |
| } |
| buf[len] = '\0'; |
| if (strncmp(buf, kShutdownToken, arraysize(kShutdownToken) - 1) == 0) { |
| // The other process is shutting down, it's safe to start a new process. |
| + SendRemoteProcessInteractionResultHistogram(REMOTE_PROCESS_SHUTTING_DOWN); |
| return PROCESS_NONE; |
| } else if (strncmp(buf, kACKToken, arraysize(kACKToken) - 1) == 0) { |
| #if defined(TOOLKIT_VIEWS) && defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| @@ -945,6 +969,10 @@ void ProcessSingleton::DisablePromptForTesting() { |
| g_disable_prompt = true; |
| } |
| +void ProcessSingleton::SkipIsChromeProcessCheckForTesting() { |
| + g_skip_is_chrome_process_check = true; |
| +} |
| + |
| bool ProcessSingleton::Create() { |
| int sock; |
| sockaddr_un addr; |
| @@ -1057,18 +1085,26 @@ bool ProcessSingleton::KillProcessByLockPath() { |
| ParseLockPath(lock_path_, &hostname, &pid); |
| if (!hostname.empty() && hostname != net::GetHostName()) { |
| - return DisplayProfileInUseError(lock_path_, hostname, pid); |
| + bool res = DisplayProfileInUseError(lock_path_, hostname, pid); |
| + if (res) |
| + SendRemoteProcessInteractionResultHistogram(PROFILE_UNLOCKED_BEFORE_KILL); |
| + return res; |
| } |
| UnlinkPath(lock_path_); |
| - if (IsSameChromeInstance(pid)) |
| + if (IsSameChromeInstance(pid)) { |
| + SendRemoteProcessInteractionResultHistogram( |
| + SAME_BROWSER_INSTANCE_BEFORE_KILL); |
| return true; |
| + } |
| if (pid > 0) { |
| kill_callback_.Run(pid); |
| return true; |
| } |
| + SendRemoteProcessInteractionResultHistogram(FAILED_TO_EXTRACT_PID); |
| + |
| LOG(ERROR) << "Failed to extract pid from path: " << lock_path_.value(); |
| return true; |
| } |
| @@ -1080,4 +1116,24 @@ void ProcessSingleton::KillProcess(int pid) { |
| // progress of shutting down and finishes before we try to kill it). |
| DCHECK(rv == 0 || errno == ESRCH) << "Error killing process: " |
| << base::safe_strerror(errno); |
| + |
| + int error_code = (rv == 0) ? 0 : errno; |
| + UMA_HISTOGRAM_SPARSE_SLOWLY( |
| + "Chrome.ProcessSingleton.TerminateProcessErrorCode.Posix", error_code); |
| + |
| + RemoteProcessInteractionResult action = TERMINATE_SUCCEEDED; |
| + if (rv != 0) { |
| + switch (error_code) { |
| + case ESRCH: |
| + action = REMOTE_PROCESS_NOT_FOUND; |
| + break; |
| + case EPERM: |
| + action = TERMINATE_NOT_ENOUGH_PERMISSIONS; |
| + break; |
| + default: |
| + action = TERMINATE_FAILED; |
| + break; |
| + } |
| + } |
| + SendRemoteProcessInteractionResultHistogram(action); |
| } |