| Index: chrome/browser/process_singleton_posix.cc
|
| diff --git a/chrome/browser/process_singleton_posix.cc b/chrome/browser/process_singleton_posix.cc
|
| index 35e711ecd6a014501d4ffaadd3d0b26b50e87e88..559247647d0e125e7c0f07809fa2fef69e04adfa 100644
|
| --- a/chrome/browser/process_singleton_posix.cc
|
| +++ b/chrome/browser/process_singleton_posix.cc
|
| @@ -92,10 +92,14 @@
|
|
|
| using content::BrowserThread;
|
|
|
| -const int ProcessSingleton::kTimeoutInSeconds;
|
| -
|
| namespace {
|
|
|
| +// Timeout for the current browser process to respond. 20 seconds should be
|
| +// enough.
|
| +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;
|
| const char kStartToken[] = "START";
|
| const char kACKToken[] = "ACK";
|
| @@ -158,26 +162,34 @@ bool WriteToSocket(int fd, const char *message, size_t length) {
|
| return true;
|
| }
|
|
|
| -// Wait a socket for read for a certain timeout in seconds.
|
| +struct timeval TimeDeltaToTimeVal(const base::TimeDelta& delta) {
|
| + struct timeval result;
|
| + result.tv_sec = delta.InSeconds();
|
| + result.tv_usec = delta.InMicroseconds() % base::Time::kMicrosecondsPerSecond;
|
| + return result;
|
| +}
|
| +
|
| +// Wait a socket for read for a certain timeout.
|
| // Returns -1 if error occurred, 0 if timeout reached, > 0 if the socket is
|
| // ready for read.
|
| -int WaitSocketForRead(int fd, int timeout) {
|
| +int WaitSocketForRead(int fd, const base::TimeDelta& timeout) {
|
| fd_set read_fds;
|
| - struct timeval tv;
|
| + struct timeval tv = TimeDeltaToTimeVal(timeout);
|
|
|
| FD_ZERO(&read_fds);
|
| FD_SET(fd, &read_fds);
|
| - tv.tv_sec = timeout;
|
| - tv.tv_usec = 0;
|
|
|
| return HANDLE_EINTR(select(fd + 1, &read_fds, NULL, NULL, &tv));
|
| }
|
|
|
| -// Read a message from a socket fd, with an optional timeout in seconds.
|
| +// Read a message from a socket fd, with an optional timeout.
|
| // If |timeout| <= 0 then read immediately.
|
| // Return number of bytes actually read, or -1 on error.
|
| -ssize_t ReadFromSocket(int fd, char *buf, size_t bufsize, int timeout) {
|
| - if (timeout > 0) {
|
| +ssize_t ReadFromSocket(int fd,
|
| + char* buf,
|
| + size_t bufsize,
|
| + const base::TimeDelta& timeout) {
|
| + if (timeout > base::TimeDelta()) {
|
| int rv = WaitSocketForRead(fd, timeout);
|
| if (rv <= 0)
|
| return rv;
|
| @@ -744,19 +756,25 @@ ProcessSingleton::~ProcessSingleton() {
|
| }
|
|
|
| ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcess() {
|
| - return NotifyOtherProcessWithTimeout(*CommandLine::ForCurrentProcess(),
|
| - kTimeoutInSeconds,
|
| - true);
|
| + return NotifyOtherProcessWithTimeout(
|
| + *CommandLine::ForCurrentProcess(),
|
| + kRetryAttempts,
|
| + base::TimeDelta::FromSeconds(kTimeoutInSeconds),
|
| + true);
|
| }
|
|
|
| ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
|
| const CommandLine& cmd_line,
|
| - int timeout_seconds,
|
| + int retry_attempts,
|
| + const base::TimeDelta& timeout,
|
| bool kill_unresponsive) {
|
| - DCHECK_GE(timeout_seconds, 0);
|
| + DCHECK_GE(retry_attempts, 0);
|
| + DCHECK_GE(timeout.InMicroseconds(), 0);
|
| +
|
| + base::TimeDelta sleep_interval = timeout / retry_attempts;
|
|
|
| ScopedSocket socket;
|
| - for (int retries = 0; retries <= timeout_seconds; ++retries) {
|
| + for (int retries = 0; retries <= retry_attempts; ++retries) {
|
| // Try to connect to the socket.
|
| if (ConnectSocket(&socket, socket_path_, cookie_path_))
|
| break;
|
| @@ -764,7 +782,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
|
| // If we're in a race with another process, they may be in Create() and have
|
| // created the lock but not attached to the socket. So we check if the
|
| // process with the pid from the lockfile is currently running and is a
|
| - // chrome browser. If so, we loop and try again for |timeout_seconds|.
|
| + // chrome browser. If so, we loop and try again for |timeout|.
|
|
|
| std::string hostname;
|
| int pid;
|
| @@ -802,18 +820,22 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
|
| return PROCESS_NONE;
|
| }
|
|
|
| - if (retries == timeout_seconds) {
|
| + if (retries == retry_attempts) {
|
| // Retries failed. Kill the unresponsive chrome process and continue.
|
| if (!kill_unresponsive || !KillProcessByLockPath())
|
| return PROFILE_IN_USE;
|
| return PROCESS_NONE;
|
| }
|
|
|
| - base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
|
| + base::PlatformThread::Sleep(sleep_interval);
|
| }
|
|
|
| - timeval timeout = {timeout_seconds, 0};
|
| - setsockopt(socket.fd(), SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
|
| + timeval socket_timeout = TimeDeltaToTimeVal(timeout);
|
| + setsockopt(socket.fd(),
|
| + SOL_SOCKET,
|
| + SO_SNDTIMEO,
|
| + &socket_timeout,
|
| + sizeof(socket_timeout));
|
|
|
| // Found another process, prepare our command line
|
| // format is "START\0<current dir>\0<argv[0]>\0...\0<argv[n]>".
|
| @@ -846,8 +868,7 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
|
| // Read ACK message from the other process. It might be blocked for a certain
|
| // timeout, to make sure the other process has enough time to return ACK.
|
| char buf[kMaxACKMessageLength + 1];
|
| - ssize_t len =
|
| - ReadFromSocket(socket.fd(), buf, kMaxACKMessageLength, timeout_seconds);
|
| + ssize_t len = ReadFromSocket(socket.fd(), buf, kMaxACKMessageLength, timeout);
|
|
|
| // Failed to read ACK, the other process might have been frozen.
|
| if (len <= 0) {
|
| @@ -879,15 +900,17 @@ ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessWithTimeout(
|
| ProcessSingleton::NotifyResult ProcessSingleton::NotifyOtherProcessOrCreate() {
|
| return NotifyOtherProcessWithTimeoutOrCreate(
|
| *CommandLine::ForCurrentProcess(),
|
| - kTimeoutInSeconds);
|
| + kRetryAttempts,
|
| + base::TimeDelta::FromSeconds(kTimeoutInSeconds));
|
| }
|
|
|
| ProcessSingleton::NotifyResult
|
| ProcessSingleton::NotifyOtherProcessWithTimeoutOrCreate(
|
| const CommandLine& command_line,
|
| - int timeout_seconds) {
|
| - NotifyResult result = NotifyOtherProcessWithTimeout(command_line,
|
| - timeout_seconds, true);
|
| + int retry_attempts,
|
| + const base::TimeDelta& timeout) {
|
| + NotifyResult result = NotifyOtherProcessWithTimeout(
|
| + command_line, retry_attempts, timeout, true);
|
| if (result != PROCESS_NONE)
|
| return result;
|
| if (Create())
|
| @@ -897,7 +920,8 @@ ProcessSingleton::NotifyOtherProcessWithTimeoutOrCreate(
|
| // we did.)
|
| // This time, we don't want to kill anything if we aren't successful, since we
|
| // aren't going to try to take over the lock ourselves.
|
| - result = NotifyOtherProcessWithTimeout(command_line, timeout_seconds, false);
|
| + result = NotifyOtherProcessWithTimeout(
|
| + command_line, retry_attempts, timeout, false);
|
| if (result != PROCESS_NONE)
|
| return result;
|
|
|
|
|