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

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

Issue 160436: It's a copy of http://codereview.chromium.org/155772, with the fix for valgri... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « chrome/browser/process_singleton.h ('k') | chrome/browser/process_singleton_linux_uitest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 //
11 // The socket file's name contains the process id of chrome's browser process,
12 // eg. "SingletonSocket-9156". A symbol link named "SingletonSocket" will be
13 // created and pointed to the real socket file, so they would look like:
14 //
15 // SingletonSocket -> SingletonSocket-9156
16 // SingletonSocket-9156
17 //
18 // So that the socket file can be connected through "SingletonSocket" and the
19 // process id can also be retrieved from it by calling readlink().
20 //
21 // When the second process sends the current directory and command line flags to
22 // the first process, it waits for an ACK message back from the first process
23 // for a certain time. If there is no ACK message back in time, then the first
24 // process will be considered as hung for some reason. The second process then
25 // retrieves the process id from the symbol link and kills it by sending
26 // SIGKILL. Then the second process starts as normal.
27 //
28 // TODO(james.su@gmail.com): Add unittest for this class.
10 29
11 #include "chrome/browser/process_singleton.h" 30 #include "chrome/browser/process_singleton.h"
12 31
13 #include <errno.h> 32 #include <errno.h>
14 #include <fcntl.h> 33 #include <fcntl.h>
34 #include <signal.h>
35 #include <sys/socket.h>
36 #include <sys/stat.h>
15 #include <sys/types.h> 37 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/un.h> 38 #include <sys/un.h>
39 #include <unistd.h>
40 #include <cstring>
18 #include <set> 41 #include <set>
42 #include <string>
19 43
20 #include "base/base_paths.h" 44 #include "base/base_paths.h"
21 #include "base/basictypes.h" 45 #include "base/basictypes.h"
22 #include "base/command_line.h" 46 #include "base/command_line.h"
23 #include "base/eintr_wrapper.h" 47 #include "base/eintr_wrapper.h"
24 #include "base/logging.h" 48 #include "base/logging.h"
25 #include "base/message_loop.h" 49 #include "base/message_loop.h"
26 #include "base/path_service.h" 50 #include "base/path_service.h"
51 #include "base/process_util.h"
27 #include "base/stl_util-inl.h" 52 #include "base/stl_util-inl.h"
28 #include "base/string_util.h" 53 #include "base/string_util.h"
29 #include "base/time.h" 54 #include "base/time.h"
30 #include "base/timer.h" 55 #include "base/timer.h"
31 #include "chrome/browser/browser_init.h" 56 #include "chrome/browser/browser_init.h"
32 #include "chrome/browser/browser_process.h" 57 #include "chrome/browser/browser_process.h"
33 #include "chrome/browser/chrome_thread.h" 58 #include "chrome/browser/chrome_thread.h"
34 #include "chrome/browser/profile.h" 59 #include "chrome/browser/profile.h"
35 #include "chrome/browser/profile_manager.h" 60 #include "chrome/browser/profile_manager.h"
36 #include "chrome/common/chrome_constants.h" 61 #include "chrome/common/chrome_constants.h"
37 #include "chrome/common/chrome_paths.h" 62 #include "chrome/common/chrome_paths.h"
38 63
64 const int ProcessSingleton::kTimeoutInSeconds;
65
39 namespace { 66 namespace {
40 67
41 const char kStartToken[] = "START"; 68 const char kStartToken[] = "START";
69 const char kACKToken[] = "ACK";
70 const char kShutdownToken[] = "SHUTDOWN";
42 const char kTokenDelimiter = '\0'; 71 const char kTokenDelimiter = '\0';
43 const int kTimeOutInSeconds = 5;
44 const int kMaxMessageLength = 32 * 1024; 72 const int kMaxMessageLength = 32 * 1024;
73 const int kMaxACKMessageLength = arraysize(kShutdownToken) - 1;
45 74
46 // Set a file descriptor to be non-blocking. 75 // Set a file descriptor to be non-blocking.
47 // Return 0 on success, -1 on failure. 76 // Return 0 on success, -1 on failure.
48 int SetNonBlocking(int fd) { 77 int SetNonBlocking(int fd) {
49 int flags = fcntl(fd, F_GETFL, 0); 78 int flags = fcntl(fd, F_GETFL, 0);
50 if (-1 == flags) 79 if (-1 == flags)
51 return flags; 80 return flags;
52 if (flags & O_NONBLOCK) 81 if (flags & O_NONBLOCK)
53 return 0; 82 return 0;
54 return fcntl(fd, F_SETFL, flags | O_NONBLOCK); 83 return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
55 } 84 }
56 85
57 // Set the close-on-exec bit on a file descriptor. 86 // Set the close-on-exec bit on a file descriptor.
58 // Returns 0 on success, -1 on failure. 87 // Returns 0 on success, -1 on failure.
59 int SetCloseOnExec(int fd) { 88 int SetCloseOnExec(int fd) {
60 int flags = fcntl(fd, F_GETFD, 0); 89 int flags = fcntl(fd, F_GETFD, 0);
61 if (-1 == flags) 90 if (-1 == flags)
62 return flags; 91 return flags;
63 if (flags & FD_CLOEXEC) 92 if (flags & FD_CLOEXEC)
64 return 0; 93 return 0;
65 return fcntl(fd, F_SETFD, flags | FD_CLOEXEC); 94 return fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
66 } 95 }
67 96
97 // Close a socket and check return value.
98 void CloseSocket(int fd) {
99 int rv = HANDLE_EINTR(close(fd));
100 DCHECK_EQ(0, rv) << "Error closing socket: " << strerror(errno);
101 }
102
103 // Write a message to a socket fd.
104 bool WriteToSocket(int fd, const char *message, size_t length) {
105 DCHECK(message);
106 DCHECK(length);
107 size_t bytes_written = 0;
108 do {
109 ssize_t rv = HANDLE_EINTR(
110 write(fd, message + bytes_written, length - bytes_written));
111 if (rv < 0) {
112 if (errno == EAGAIN || errno == EWOULDBLOCK) {
113 // The socket shouldn't block, we're sending so little data. Just give
114 // up here, since NotifyOtherProcess() doesn't have an asynchronous api.
115 LOG(ERROR) << "ProcessSingleton would block on write(), so it gave up.";
116 return false;
117 }
118 LOG(ERROR) << "write() failed: " << strerror(errno);
119 return false;
120 }
121 bytes_written += rv;
122 } while (bytes_written < length);
123
124 return true;
125 }
126
127 // Wait a socket for read for a certain timeout in seconds.
128 // Returns -1 if error occurred, 0 if timeout reached, > 0 if the socket is
129 // ready for read.
130 int WaitSocketForRead(int fd, int timeout) {
131 fd_set read_fds;
132 struct timeval tv;
133
134 FD_ZERO(&read_fds);
135 FD_SET(fd, &read_fds);
136 tv.tv_sec = timeout;
137 tv.tv_usec = 0;
138
139 return HANDLE_EINTR(select(fd + 1, &read_fds, NULL, NULL, &tv));
140 }
141
142 // Read a message from a socket fd, with an optional timeout in seconds.
143 // If |timeout| <= 0 then read immediately.
144 // Return number of bytes actually read, or -1 on error.
145 ssize_t ReadFromSocket(int fd, char *buf, size_t bufsize, int timeout) {
146 if (timeout > 0) {
147 int rv = WaitSocketForRead(fd, timeout);
148 if (rv <= 0)
149 return rv;
150 }
151
152 size_t bytes_read = 0;
153 do {
154 ssize_t rv = HANDLE_EINTR(read(fd, buf + bytes_read, bufsize - bytes_read));
155 if (rv < 0) {
156 if (errno != EAGAIN && errno != EWOULDBLOCK) {
157 LOG(ERROR) << "read() failed: " << strerror(errno);
158 return rv;
159 } else {
160 // It would block, so we just return what has been read.
161 return bytes_read;
162 }
163 } else if (!rv) {
164 // No more data to read.
165 return bytes_read;
166 } else {
167 bytes_read += rv;
168 }
169 } while (bytes_read < bufsize);
170
171 return bytes_read;
172 }
173
174 // Set up a socket and sockaddr appropriate for messaging.
175 void SetupSocket(const std::string& path, int* sock, struct sockaddr_un* addr) {
176 *sock = socket(PF_UNIX, SOCK_STREAM, 0);
177 CHECK(*sock >= 0) << "socket() failed: " << strerror(errno);
178
179 int rv = SetNonBlocking(*sock);
180 DCHECK_EQ(0, rv) << "Failed to make non-blocking socket.";
181 rv = SetCloseOnExec(*sock);
182 DCHECK_EQ(0, rv) << "Failed to set CLOEXEC on socket.";
183
184 addr->sun_family = AF_UNIX;
185 CHECK(path.length() < arraysize(addr->sun_path))
186 << "Socket path too long: " << path;
187 base::strlcpy(addr->sun_path, path.c_str(), arraysize(addr->sun_path));
188 }
189
190 // Read a symbol link, return empty string if given path is not a symbol link.
191 std::string ReadLink(const std::string& path) {
192 struct stat statbuf;
193
194 if (lstat(path.c_str(), &statbuf) < 0) {
195 DCHECK_EQ(errno, ENOENT);
196 return std::string();
197 }
198
199 if (S_ISLNK(statbuf.st_mode)) {
200 char buf[PATH_MAX + 1];
201 ssize_t len = readlink(path.c_str(), buf, PATH_MAX);
202 if (len > 0) {
203 buf[len] = '\0';
204 FilePath real_path(buf);
205 // If it's not an absolute path, then it's necessary to prepend the
206 // original path's dirname.
207 if (!real_path.IsAbsolute()) {
208 real_path = FilePath(path).DirName().Append(real_path);
209 }
210 return real_path.value();
211 } else {
212 LOG(ERROR) << "readlink(" << path << ") failed: " << strerror(errno);
213 }
214 }
215
216 return std::string();
217 }
218
219 // Unlink a socket path. If the path is a symbol link, then the symbol link
220 // and the real path referenced by the symbol link will be unlinked together.
221 bool UnlinkSocketPath(const std::string& path) {
222 std::string real_path = ReadLink(path);
223
224 bool ret = true;
225 if (real_path.length())
226 ret = UnlinkSocketPath(real_path);
227
228 int rv = unlink(path.c_str());
229 if (rv < 0)
230 DCHECK_EQ(errno, ENOENT);
231
232 return rv == 0 && ret;
233 }
234
235 // Extract the process's pid from a symbol link path and kill it.
236 // The pid will be appended to the end of path with a preceding dash, such as:
237 // .../SingletonSocket-1234
238 void KillProcessBySocketPath(const std::string& path) {
239 std::string real_path = ReadLink(path);
240
241 // If the path is not a symbol link, try to extract pid from the path itself.
242 if (real_path.empty())
243 real_path = path;
244
245 // Only extract pid from the base name, to avoid finding wrong value from its
246 // parent path name.
247 std::string base_name = FilePath(real_path).BaseName().value();
248 DCHECK(base_name.length());
249
250 std::string::size_type pos = base_name.rfind('-');
251 if (pos != std::string::npos) {
252 std::string pid_str = base_name.substr(pos + 1);
253 int pid;
254 if (StringToInt(pid_str, &pid)) {
255 // TODO(james.su@gmail.com): Is SIGKILL ok?
256 int rv = kill(static_cast<base::ProcessHandle>(pid), SIGKILL);
257 DCHECK_EQ(0, rv) << "Error killing process:" << strerror(errno);
258 return;
259 }
260 }
261
262 LOG(ERROR) << "Failed to extract pid from path: " << real_path;
263 }
264
265 // A helper class to close a socket automatically.
266 class SocketCloser {
267 public:
268 explicit SocketCloser(int fd) : fd_(fd) { }
269 ~SocketCloser() { CloseSocket(fd_); }
270 private:
271 int fd_;
272 };
273
68 } // namespace 274 } // namespace
69 275
70 /////////////////////////////////////////////////////////////////////////////// 276 ///////////////////////////////////////////////////////////////////////////////
71 // ProcessSingleton::LinuxWatcher 277 // ProcessSingleton::LinuxWatcher
72 // A helper class for a Linux specific implementation of the process singleton. 278 // A helper class for a Linux specific implementation of the process singleton.
73 // This class sets up a listener on the singleton socket and handles parsing 279 // This class sets up a listener on the singleton socket and handles parsing
74 // messages that come in on the singleton socket. 280 // messages that come in on the singleton socket.
75 class ProcessSingleton::LinuxWatcher 281 class ProcessSingleton::LinuxWatcher
76 : public MessageLoopForIO::Watcher, 282 : public MessageLoopForIO::Watcher,
77 public MessageLoop::DestructionObserver, 283 public MessageLoop::DestructionObserver,
78 public base::RefCountedThreadSafe<ProcessSingleton::LinuxWatcher> { 284 public base::RefCountedThreadSafe<ProcessSingleton::LinuxWatcher> {
79 public: 285 public:
80 // We expect to only be constructed on the UI thread. 286 // A helper class to read message from an established socket.
81 explicit LinuxWatcher(ProcessSingleton* parent)
82 : ui_message_loop_(MessageLoop::current()),
83 parent_(parent) {
84 }
85
86 virtual ~LinuxWatcher() {
87 STLDeleteElements(&readers_);
88 }
89
90 // Start listening for connections on the socket. This method should be
91 // called from the IO thread.
92 void StartListening(int socket);
93
94 // This method determines if we should use the same process and if we should,
95 // opens a new browser tab. This runs on the UI thread.
96 void HandleMessage(std::string current_dir, std::vector<std::string> argv);
97
98 // MessageLoopForIO::Watcher impl. These run on the IO thread.
99 virtual void OnFileCanReadWithoutBlocking(int fd);
100 virtual void OnFileCanWriteWithoutBlocking(int fd) {
101 // ProcessSingleton only watches for accept (read) events.
102 NOTREACHED();
103 }
104
105 // MessageLoop::DestructionObserver
106 virtual void WillDestroyCurrentMessageLoop() {
107 fd_watcher_.StopWatchingFileDescriptor();
108 }
109
110 private:
111 class SocketReader : public MessageLoopForIO::Watcher { 287 class SocketReader : public MessageLoopForIO::Watcher {
112 public: 288 public:
113 SocketReader(ProcessSingleton::LinuxWatcher* parent, 289 SocketReader(ProcessSingleton::LinuxWatcher* parent,
114 MessageLoop* ui_message_loop, 290 MessageLoop* ui_message_loop,
115 int fd) 291 int fd)
116 : parent_(parent), 292 : parent_(parent),
117 ui_message_loop_(ui_message_loop), 293 ui_message_loop_(ui_message_loop),
118 fd_(fd), 294 fd_(fd),
119 bytes_read_(0) { 295 bytes_read_(0) {
120 // Wait for reads. 296 // Wait for reads.
121 MessageLoopForIO::current()->WatchFileDescriptor( 297 MessageLoopForIO::current()->WatchFileDescriptor(
122 fd, true, MessageLoopForIO::WATCH_READ, &fd_reader_, this); 298 fd, true, MessageLoopForIO::WATCH_READ, &fd_reader_, this);
123 timer_.Start(base::TimeDelta::FromSeconds(kTimeOutInSeconds), 299 timer_.Start(base::TimeDelta::FromSeconds(kTimeoutInSeconds),
124 this, &SocketReader::OnTimerExpiry); 300 this, &SocketReader::OnTimerExpiry);
125 } 301 }
126 302
127 virtual ~SocketReader() { 303 virtual ~SocketReader() {
128 int rv = HANDLE_EINTR(close(fd_)); 304 CloseSocket(fd_);
129 DCHECK_EQ(0, rv) << "Error closing socket: " << strerror(errno);
130 } 305 }
131 306
132 // MessageLoopForIO::Watcher impl. 307 // MessageLoopForIO::Watcher impl.
133 virtual void OnFileCanReadWithoutBlocking(int fd); 308 virtual void OnFileCanReadWithoutBlocking(int fd);
134 virtual void OnFileCanWriteWithoutBlocking(int fd) { 309 virtual void OnFileCanWriteWithoutBlocking(int fd) {
135 // SocketReader only watches for accept (read) events. 310 // SocketReader only watches for accept (read) events.
136 NOTREACHED(); 311 NOTREACHED();
137 } 312 }
138 313
314 // Finish handling the incoming message by optionally sending back an ACK
315 // message and removing this SocketReader.
316 void FinishWithACK(const char *message, size_t length);
317
139 private: 318 private:
140 // If we haven't completed in a reasonable amount of time, give up. 319 // If we haven't completed in a reasonable amount of time, give up.
141 void OnTimerExpiry() { 320 void OnTimerExpiry() {
142 parent_->RemoveSocketReader(this); 321 parent_->RemoveSocketReader(this);
143 // We're deleted beyond this point. 322 // We're deleted beyond this point.
144 } 323 }
145 324
146 MessageLoopForIO::FileDescriptorWatcher fd_reader_; 325 MessageLoopForIO::FileDescriptorWatcher fd_reader_;
147 326
148 // The ProcessSingleton::LinuxWatcher that owns us. 327 // The ProcessSingleton::LinuxWatcher that owns us.
(...skipping 10 matching lines...) Expand all
159 338
160 // Tracks the number of bytes we've read in case we're getting partial 339 // Tracks the number of bytes we've read in case we're getting partial
161 // reads. 340 // reads.
162 size_t bytes_read_; 341 size_t bytes_read_;
163 342
164 base::OneShotTimer<SocketReader> timer_; 343 base::OneShotTimer<SocketReader> timer_;
165 344
166 DISALLOW_COPY_AND_ASSIGN(SocketReader); 345 DISALLOW_COPY_AND_ASSIGN(SocketReader);
167 }; 346 };
168 347
348 // We expect to only be constructed on the UI thread.
349 explicit LinuxWatcher(ProcessSingleton* parent)
350 : ui_message_loop_(MessageLoop::current()),
351 parent_(parent) {
352 }
353
354 virtual ~LinuxWatcher() {
355 STLDeleteElements(&readers_);
356 }
357
358 // Start listening for connections on the socket. This method should be
359 // called from the IO thread.
360 void StartListening(int socket);
361
362 // This method determines if we should use the same process and if we should,
363 // opens a new browser tab. This runs on the UI thread.
364 // |reader| is for sending back ACK message.
365 void HandleMessage(const std::string& current_dir,
366 const std::vector<std::string>& argv,
367 SocketReader *reader);
368
369 // MessageLoopForIO::Watcher impl. These run on the IO thread.
370 virtual void OnFileCanReadWithoutBlocking(int fd);
371 virtual void OnFileCanWriteWithoutBlocking(int fd) {
372 // ProcessSingleton only watches for accept (read) events.
373 NOTREACHED();
374 }
375
376 // MessageLoop::DestructionObserver
377 virtual void WillDestroyCurrentMessageLoop() {
378 fd_watcher_.StopWatchingFileDescriptor();
379 }
380
381 private:
169 // Removes and deletes the SocketReader. 382 // Removes and deletes the SocketReader.
170 void RemoveSocketReader(SocketReader* reader); 383 void RemoveSocketReader(SocketReader* reader);
171 384
172 MessageLoopForIO::FileDescriptorWatcher fd_watcher_; 385 MessageLoopForIO::FileDescriptorWatcher fd_watcher_;
173 386
174 // A reference to the UI message loop (i.e., the message loop we were 387 // A reference to the UI message loop (i.e., the message loop we were
175 // constructed on). 388 // constructed on).
176 MessageLoop* ui_message_loop_; 389 MessageLoop* ui_message_loop_;
177 390
178 // The ProcessSingleton that owns us. 391 // The ProcessSingleton that owns us.
179 ProcessSingleton* const parent_; 392 ProcessSingleton* const parent_;
180 393
181 std::set<SocketReader*> readers_; 394 std::set<SocketReader*> readers_;
182 395
183 DISALLOW_COPY_AND_ASSIGN(LinuxWatcher); 396 DISALLOW_COPY_AND_ASSIGN(LinuxWatcher);
184 }; 397 };
185 398
186 void ProcessSingleton::LinuxWatcher::OnFileCanReadWithoutBlocking(int fd) { 399 void ProcessSingleton::LinuxWatcher::OnFileCanReadWithoutBlocking(int fd) {
187 // Accepting incoming client. 400 // Accepting incoming client.
188 sockaddr_un from; 401 sockaddr_un from;
189 socklen_t from_len = sizeof(from); 402 socklen_t from_len = sizeof(from);
190 int connection_socket = HANDLE_EINTR(accept( 403 int connection_socket = HANDLE_EINTR(accept(
191 fd, reinterpret_cast<sockaddr*>(&from), &from_len)); 404 fd, reinterpret_cast<sockaddr*>(&from), &from_len));
192 if (-1 == connection_socket) { 405 if (-1 == connection_socket) {
193 LOG(ERROR) << "accept() failed: " << strerror(errno); 406 LOG(ERROR) << "accept() failed: " << strerror(errno);
194 return; 407 return;
195 } 408 }
409 int rv = SetNonBlocking(connection_socket);
410 DCHECK_EQ(0, rv) << "Failed to make non-blocking socket.";
196 SocketReader* reader = new SocketReader(this, 411 SocketReader* reader = new SocketReader(this,
197 ui_message_loop_, 412 ui_message_loop_,
198 connection_socket); 413 connection_socket);
199 readers_.insert(reader); 414 readers_.insert(reader);
200 } 415 }
201 416
202 void ProcessSingleton::LinuxWatcher::StartListening(int socket) { 417 void ProcessSingleton::LinuxWatcher::StartListening(int socket) {
203 DCHECK(ChromeThread::GetMessageLoop(ChromeThread::IO) == 418 DCHECK(ChromeThread::GetMessageLoop(ChromeThread::IO) ==
204 MessageLoop::current()); 419 MessageLoop::current());
205 // Watch for client connections on this socket. 420 // Watch for client connections on this socket.
206 MessageLoopForIO* ml = MessageLoopForIO::current(); 421 MessageLoopForIO* ml = MessageLoopForIO::current();
207 ml->AddDestructionObserver(this); 422 ml->AddDestructionObserver(this);
208 ml->WatchFileDescriptor(socket, true, MessageLoopForIO::WATCH_READ, 423 ml->WatchFileDescriptor(socket, true, MessageLoopForIO::WATCH_READ,
209 &fd_watcher_, this); 424 &fd_watcher_, this);
210 } 425 }
211 426
212 void ProcessSingleton::LinuxWatcher::HandleMessage(std::string current_dir, 427 void ProcessSingleton::LinuxWatcher::HandleMessage(
213 std::vector<std::string> argv) { 428 const std::string& current_dir, const std::vector<std::string>& argv,
429 SocketReader* reader) {
214 DCHECK(ui_message_loop_ == MessageLoop::current()); 430 DCHECK(ui_message_loop_ == MessageLoop::current());
431 DCHECK(reader);
215 // Ignore the request if the browser process is already in shutdown path. 432 // Ignore the request if the browser process is already in shutdown path.
216 if (!g_browser_process || g_browser_process->IsShuttingDown()) { 433 if (!g_browser_process || g_browser_process->IsShuttingDown()) {
217 LOG(WARNING) << "Not handling interprocess notification as browser" 434 LOG(WARNING) << "Not handling interprocess notification as browser"
218 " is shutting down"; 435 " is shutting down";
436 // Send back "SHUTDOWN" message, so that the client process can start up
437 // without killing this process.
438 reader->FinishWithACK(kShutdownToken, arraysize(kShutdownToken) - 1);
219 return; 439 return;
220 } 440 }
221 441
222 // If locked, it means we are not ready to process this message because 442 // If locked, it means we are not ready to process this message because
223 // we are probably in a first run critical phase. 443 // we are probably in a first run critical phase.
224 if (parent_->locked()) { 444 if (parent_->locked()) {
225 DLOG(WARNING) << "Browser is locked"; 445 DLOG(WARNING) << "Browser is locked";
446 // Send back "ACK" message to prevent the client process from starting up.
447 reader->FinishWithACK(kACKToken, arraysize(kACKToken) - 1);
226 return; 448 return;
227 } 449 }
228 450
229 CommandLine parsed_command_line(argv); 451 CommandLine parsed_command_line(argv);
230 PrefService* prefs = g_browser_process->local_state(); 452 PrefService* prefs = g_browser_process->local_state();
231 DCHECK(prefs); 453 DCHECK(prefs);
232 454
233 FilePath user_data_dir; 455 FilePath user_data_dir;
234 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); 456 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
235 ProfileManager* profile_manager = g_browser_process->profile_manager(); 457 ProfileManager* profile_manager = g_browser_process->profile_manager();
236 Profile* profile = profile_manager->GetDefaultProfile(user_data_dir); 458 Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
237 if (!profile) { 459 if (!profile) {
238 // We should only be able to get here if the profile already exists and 460 // We should only be able to get here if the profile already exists and
239 // has been created. 461 // has been created.
240 NOTREACHED(); 462 NOTREACHED();
241 return; 463 return;
242 } 464 }
243 465
244 // TODO(tc): Send an ACK response on success.
245
246 // Run the browser startup sequence again, with the command line of the 466 // Run the browser startup sequence again, with the command line of the
247 // signalling process. 467 // signalling process.
248 FilePath current_dir_file_path(current_dir); 468 FilePath current_dir_file_path(current_dir);
249 BrowserInit::ProcessCommandLine(parsed_command_line, 469 BrowserInit::ProcessCommandLine(parsed_command_line,
250 current_dir_file_path.ToWStringHack(), 470 current_dir_file_path.ToWStringHack(),
251 false, profile, NULL); 471 false, profile, NULL);
472
473 // Send back "ACK" message to prevent the client process from starting up.
474 reader->FinishWithACK(kACKToken, arraysize(kACKToken) - 1);
252 } 475 }
253 476
254 void ProcessSingleton::LinuxWatcher::RemoveSocketReader(SocketReader* reader) { 477 void ProcessSingleton::LinuxWatcher::RemoveSocketReader(SocketReader* reader) {
255 DCHECK(reader); 478 DCHECK(reader);
256 readers_.erase(reader); 479 readers_.erase(reader);
257 delete reader; 480 delete reader;
258 } 481 }
259 482
260 /////////////////////////////////////////////////////////////////////////////// 483 ///////////////////////////////////////////////////////////////////////////////
261 // ProcessSingleton::LinuxWatcher::SocketReader 484 // ProcessSingleton::LinuxWatcher::SocketReader
262 // 485 //
263 486
264 void ProcessSingleton::LinuxWatcher::SocketReader::OnFileCanReadWithoutBlocking( 487 void ProcessSingleton::LinuxWatcher::SocketReader::OnFileCanReadWithoutBlocking(
265 int fd) { 488 int fd) {
266 DCHECK_EQ(fd, fd_); 489 DCHECK_EQ(fd, fd_);
267 while (bytes_read_ < sizeof(buf_)) { 490 while (bytes_read_ < sizeof(buf_)) {
268 ssize_t rv = HANDLE_EINTR( 491 ssize_t rv = HANDLE_EINTR(
269 read(fd, buf_ + bytes_read_, sizeof(buf_) - bytes_read_)); 492 read(fd, buf_ + bytes_read_, sizeof(buf_) - bytes_read_));
270 if (rv < 0) { 493 if (rv < 0) {
271 if (errno != EAGAIN && errno != EWOULDBLOCK) { 494 if (errno != EAGAIN && errno != EWOULDBLOCK) {
272 LOG(ERROR) << "read() failed: " << strerror(errno); 495 LOG(ERROR) << "read() failed: " << strerror(errno);
273 rv = HANDLE_EINTR(close(fd)); 496 CloseSocket(fd);
274 DCHECK_EQ(0, rv) << "Error closing socket: " << strerror(errno);
275 return; 497 return;
276 } else { 498 } else {
277 // It would block, so we just return and continue to watch for the next 499 // It would block, so we just return and continue to watch for the next
278 // opportunity to read. 500 // opportunity to read.
279 return; 501 return;
280 } 502 }
281 } else if (!rv) { 503 } else if (!rv) {
282 // No more data to read. It's time to process the message. 504 // No more data to read. It's time to process the message.
283 break; 505 break;
284 } else { 506 } else {
(...skipping 11 matching lines...) Expand all
296 518
297 std::string str(buf_, bytes_read_); 519 std::string str(buf_, bytes_read_);
298 std::vector<std::string> tokens; 520 std::vector<std::string> tokens;
299 SplitString(str, kTokenDelimiter, &tokens); 521 SplitString(str, kTokenDelimiter, &tokens);
300 522
301 if (tokens.size() < 3 || tokens[0] != kStartToken) { 523 if (tokens.size() < 3 || tokens[0] != kStartToken) {
302 LOG(ERROR) << "Wrong message format: " << str; 524 LOG(ERROR) << "Wrong message format: " << str;
303 return; 525 return;
304 } 526 }
305 527
528 // Stop the expiration timer to prevent this SocketReader object from being
529 // terminated unexpectly.
530 timer_.Stop();
531
306 std::string current_dir = tokens[1]; 532 std::string current_dir = tokens[1];
307 // Remove the first two tokens. The remaining tokens should be the command 533 // Remove the first two tokens. The remaining tokens should be the command
308 // line argv array. 534 // line argv array.
309 tokens.erase(tokens.begin()); 535 tokens.erase(tokens.begin());
310 tokens.erase(tokens.begin()); 536 tokens.erase(tokens.begin());
311 537
312 // Return to the UI thread to handle opening a new browser tab. 538 // Return to the UI thread to handle opening a new browser tab.
313 ui_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( 539 ui_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
314 parent_, 540 parent_,
315 &ProcessSingleton::LinuxWatcher::HandleMessage, 541 &ProcessSingleton::LinuxWatcher::HandleMessage,
316 current_dir, 542 current_dir,
317 tokens)); 543 tokens,
544 this));
318 fd_reader_.StopWatchingFileDescriptor(); 545 fd_reader_.StopWatchingFileDescriptor();
319 546
547 // LinuxWatcher::HandleMessage() is in charge of destroying this SocketReader
548 // object by invoking SocketReader::FinishWithACK().
549 }
550
551 void ProcessSingleton::LinuxWatcher::SocketReader::FinishWithACK(
552 const char *message, size_t length) {
553 if (message && length) {
554 // Not necessary to care about the return value.
555 WriteToSocket(fd_, message, length);
556 }
557
558 if (shutdown(fd_, SHUT_WR) < 0)
559 LOG(ERROR) << "shutdown() failed: " << strerror(errno);
560
320 parent_->RemoveSocketReader(this); 561 parent_->RemoveSocketReader(this);
321 // We are deleted beyond this point. 562 // We are deleted beyond this point.
322 } 563 }
323 564
324 /////////////////////////////////////////////////////////////////////////////// 565 ///////////////////////////////////////////////////////////////////////////////
325 // ProcessSingleton 566 // ProcessSingleton
326 // 567 //
327 ProcessSingleton::ProcessSingleton(const FilePath& user_data_dir) 568 ProcessSingleton::ProcessSingleton(const FilePath& user_data_dir)
328 : locked_(false), 569 : locked_(false),
329 foreground_window_(NULL), 570 foreground_window_(NULL),
330 ALLOW_THIS_IN_INITIALIZER_LIST(watcher_(new LinuxWatcher(this))) { 571 ALLOW_THIS_IN_INITIALIZER_LIST(watcher_(new LinuxWatcher(this))) {
331 socket_path_ = user_data_dir.Append(chrome::kSingletonSocketFilename); 572 socket_path_ = user_data_dir.Append(chrome::kSingletonSocketFilename);
332 } 573 }
333 574
334 ProcessSingleton::~ProcessSingleton() { 575 ProcessSingleton::~ProcessSingleton() {
335 } 576 }
336 577
337 bool ProcessSingleton::NotifyOtherProcess() { 578 bool ProcessSingleton::NotifyOtherProcess() {
338 int socket; 579 int socket;
339 sockaddr_un addr; 580 sockaddr_un addr;
340 SetupSocket(&socket, &addr); 581 SetupSocket(socket_path_.value(), &socket, &addr);
582
583 // It'll close the socket automatically when exiting this method.
584 SocketCloser socket_closer(socket);
341 585
342 // Connecting to the socket 586 // Connecting to the socket
343 int ret = HANDLE_EINTR(connect(socket, 587 int ret = HANDLE_EINTR(connect(socket,
344 reinterpret_cast<sockaddr*>(&addr), 588 reinterpret_cast<sockaddr*>(&addr),
345 sizeof(addr))); 589 sizeof(addr)));
346 if (ret < 0) 590 if (ret < 0)
347 return false; // Tell the caller there's nobody to notify. 591 return false; // Tell the caller there's nobody to notify.
348 592
349 timeval timeout = {20, 0}; 593 timeval timeout = {20, 0};
350 setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)); 594 setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
(...skipping 10 matching lines...) Expand all
361 605
362 const std::vector<std::string>& argv = 606 const std::vector<std::string>& argv =
363 CommandLine::ForCurrentProcess()->argv(); 607 CommandLine::ForCurrentProcess()->argv();
364 for (std::vector<std::string>::const_iterator it = argv.begin(); 608 for (std::vector<std::string>::const_iterator it = argv.begin();
365 it != argv.end(); ++it) { 609 it != argv.end(); ++it) {
366 to_send.push_back(kTokenDelimiter); 610 to_send.push_back(kTokenDelimiter);
367 to_send.append(*it); 611 to_send.append(*it);
368 } 612 }
369 613
370 // Send the message 614 // Send the message
371 int bytes_written = 0; 615 if (!WriteToSocket(socket, to_send.data(), to_send.length())) {
372 const int buf_len = to_send.length(); 616 // Try to kill the other process, because it might have been dead.
373 do { 617 KillProcessBySocketPath(socket_path_.value());
374 int rv = HANDLE_EINTR( 618 return false;
375 write(socket, to_send.data() + bytes_written, buf_len - bytes_written));
376 if (rv < 0) {
377 if (errno == EAGAIN || errno == EWOULDBLOCK) {
378 // The socket shouldn't block, we're sending so little data. Just give
379 // up here, since NotifyOtherProcess() doesn't have an asynchronous api.
380 LOG(ERROR) << "ProcessSingleton would block on write(), so it gave up.";
381 return false;
382 }
383 LOG(ERROR) << "write() failed: " << strerror(errno);
384 return false;
385 }
386 bytes_written += rv;
387 } while (bytes_written < buf_len);
388
389 int rv = shutdown(socket, SHUT_WR);
390 if (rv < 0) {
391 LOG(ERROR) << "shutdown() failed: " << strerror(errno);
392 } else {
393 // TODO(tc): We should wait for an ACK, and if we don't get it in a certain
394 // time period, kill the other process.
395 } 619 }
396 620
397 rv = HANDLE_EINTR(close(socket)); 621 if (shutdown(socket, SHUT_WR) < 0)
398 DCHECK_EQ(0, rv) << strerror(errno); 622 LOG(ERROR) << "shutdown() failed: " << strerror(errno);
399 623
400 // Assume the other process is handling the request. 624 // Read ACK message from the other process. It might be blocked for a certain
625 // timeout, to make sure the other process has enough time to return ACK.
626 char buf[kMaxACKMessageLength + 1];
627 ssize_t len =
628 ReadFromSocket(socket, buf, kMaxACKMessageLength, kTimeoutInSeconds);
629
630 // Failed to read ACK, the other process might have been frozen.
631 if (len <= 0) {
632 KillProcessBySocketPath(socket_path_.value());
633 return false;
634 }
635
636 buf[len] = '\0';
637 if (strncmp(buf, kShutdownToken, arraysize(kShutdownToken) - 1) == 0) {
638 // The other process is shutting down, it's safe to start a new process.
639 return false;
640 } else if (strncmp(buf, kACKToken, arraysize(kACKToken) - 1) == 0) {
641 // Assume the other process is handling the request.
642 return true;
643 }
644
645 NOTREACHED() << "The other process returned unknown message: " << buf;
401 return true; 646 return true;
402 } 647 }
403 648
404 void ProcessSingleton::Create() { 649 void ProcessSingleton::Create() {
405 int sock; 650 int sock;
406 sockaddr_un addr; 651 sockaddr_un addr;
407 SetupSocket(&sock, &addr);
408 652
409 if (unlink(socket_path_.value().c_str()) < 0) 653 // Append the process id to the socket path, so that other process can find it
410 DCHECK_EQ(errno, ENOENT); 654 // out.
655 std::string path = StringPrintf(
656 "%s-%u", socket_path_.value().c_str(), base::GetCurrentProcId());
657 SetupSocket(path, &sock, &addr);
658
659 UnlinkSocketPath(socket_path_.value());
660
661 // Create symbol link before binding the socket, so that the socket file can
662 // always be reached and removed by another process.
663 // The symbol link only contains the filename part of the socket file, so that
664 // the whole config directory can be moved without breaking the symbol link.
665 std::string symlink_content = FilePath(path).BaseName().value();
666 if (symlink(symlink_content.c_str(), socket_path_.value().c_str()) < 0)
667 NOTREACHED() << "Failed to create symbol link: " << strerror(errno);
411 668
412 if (bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) { 669 if (bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
413 LOG(ERROR) << "bind() failed: " << strerror(errno); 670 LOG(ERROR) << "bind() failed: " << strerror(errno);
414 LOG(ERROR) << "SingletonSocket failed to create a socket in your home " 671 LOG(ERROR) << "SingletonSocket failed to create a socket in your home "
415 "directory. This means that running multiple instances of " 672 "directory. This means that running multiple instances of "
416 "the Chrome binary will start multiple browser process " 673 "the Chrome binary will start multiple browser process "
417 "rather than opening a new window in the existing process."; 674 "rather than opening a new window in the existing process.";
418 close(sock); 675 CloseSocket(sock);
419 return; 676 return;
420 } 677 }
421 678
422 if (listen(sock, 5) < 0) 679 if (listen(sock, 5) < 0)
423 NOTREACHED() << "listen failed: " << strerror(errno); 680 NOTREACHED() << "listen failed: " << strerror(errno);
424 681
425 // Normally we would use ChromeThread, but the IO thread hasn't started yet. 682 // Normally we would use ChromeThread, but the IO thread hasn't started yet.
426 // Using g_browser_process, we start the thread so we can listen on the 683 // Using g_browser_process, we start the thread so we can listen on the
427 // socket. 684 // socket.
428 MessageLoop* ml = g_browser_process->io_thread()->message_loop(); 685 MessageLoop* ml = g_browser_process->io_thread()->message_loop();
429 DCHECK(ml); 686 DCHECK(ml);
430 ml->PostTask(FROM_HERE, NewRunnableMethod( 687 ml->PostTask(FROM_HERE, NewRunnableMethod(
431 watcher_.get(), 688 watcher_.get(),
432 &ProcessSingleton::LinuxWatcher::StartListening, 689 &ProcessSingleton::LinuxWatcher::StartListening,
433 sock)); 690 sock));
434 } 691 }
435
436 void ProcessSingleton::SetupSocket(int* sock, struct sockaddr_un* addr) {
437 *sock = socket(PF_UNIX, SOCK_STREAM, 0);
438 if (*sock < 0)
439 LOG(FATAL) << "socket() failed: " << strerror(errno);
440
441 int rv = SetNonBlocking(*sock);
442 DCHECK_EQ(0, rv) << "Failed to make non-blocking socket.";
443 rv = SetCloseOnExec(*sock);
444 DCHECK_EQ(0, rv) << "Failed to set CLOEXEC on socket.";
445
446 addr->sun_family = AF_UNIX;
447 if (socket_path_.value().length() > sizeof(addr->sun_path) - 1)
448 LOG(FATAL) << "Socket path too long: " << socket_path_.value();
449 base::strlcpy(addr->sun_path, socket_path_.value().c_str(),
450 sizeof(addr->sun_path));
451 }
OLDNEW
« no previous file with comments | « chrome/browser/process_singleton.h ('k') | chrome/browser/process_singleton_linux_uitest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698