OLD | NEW |
---|---|
1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-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 #include "chrome/browser/browser_main.h" | 5 #include "chrome/browser/browser_main.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "app/hi_res_timer_manager.h" | 9 #include "app/hi_res_timer_manager.h" |
10 #include "app/l10n_util.h" | 10 #include "app/l10n_util.h" |
11 #include "app/resource_bundle.h" | 11 #include "app/resource_bundle.h" |
12 #include "app/system_monitor.h" | 12 #include "app/system_monitor.h" |
13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
14 #include "base/field_trial.h" | 14 #include "base/field_trial.h" |
15 #include "base/file_util.h" | 15 #include "base/file_util.h" |
16 #include "base/histogram.h" | 16 #include "base/histogram.h" |
17 #include "base/lazy_instance.h" | 17 #include "base/lazy_instance.h" |
18 #include "base/scoped_nsautorelease_pool.h" | 18 #include "base/scoped_nsautorelease_pool.h" |
19 #include "base/path_service.h" | 19 #include "base/path_service.h" |
20 #include "base/platform_thread.h" | |
20 #include "base/process_util.h" | 21 #include "base/process_util.h" |
21 #include "base/string_piece.h" | 22 #include "base/string_piece.h" |
22 #include "base/string_util.h" | 23 #include "base/string_util.h" |
23 #include "base/sys_string_conversions.h" | 24 #include "base/sys_string_conversions.h" |
24 #include "base/time.h" | 25 #include "base/time.h" |
25 #include "base/tracked_objects.h" | 26 #include "base/tracked_objects.h" |
26 #include "base/values.h" | 27 #include "base/values.h" |
27 #include "chrome/browser/browser_main_win.h" | 28 #include "chrome/browser/browser_main_win.h" |
28 #include "chrome/browser/browser_init.h" | 29 #include "chrome/browser/browser_init.h" |
29 #include "chrome/browser/browser_list.h" | 30 #include "chrome/browser/browser_list.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
65 #include "net/base/net_module.h" | 66 #include "net/base/net_module.h" |
66 #include "net/http/http_network_session.h" | 67 #include "net/http/http_network_session.h" |
67 #include "net/socket/client_socket_pool_base.h" | 68 #include "net/socket/client_socket_pool_base.h" |
68 | 69 |
69 #if defined(OS_POSIX) | 70 #if defined(OS_POSIX) |
70 // TODO(port): get rid of this include. It's used just to provide declarations | 71 // TODO(port): get rid of this include. It's used just to provide declarations |
71 // and stub definitions for classes we encouter during the porting effort. | 72 // and stub definitions for classes we encouter during the porting effort. |
72 #include <errno.h> | 73 #include <errno.h> |
73 #include <signal.h> | 74 #include <signal.h> |
74 #include <sys/resource.h> | 75 #include <sys/resource.h> |
76 #include "base/eintr_wrapper.h" | |
75 #endif | 77 #endif |
76 | 78 |
77 #if defined(USE_LINUX_BREAKPAD) | 79 #if defined(USE_LINUX_BREAKPAD) |
78 #include "base/linux_util.h" | 80 #include "base/linux_util.h" |
79 #include "chrome/app/breakpad_linux.h" | 81 #include "chrome/app/breakpad_linux.h" |
80 #endif | 82 #endif |
81 | 83 |
82 #if defined(OS_LINUX) | 84 #if defined(OS_LINUX) |
83 #include "chrome/common/gtk_util.h" | 85 #include "chrome/common/gtk_util.h" |
84 #endif | 86 #endif |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
161 #elif defined(OS_POSIX) | 163 #elif defined(OS_POSIX) |
162 MessageLoopForUI::current()->Run(); | 164 MessageLoopForUI::current()->Run(); |
163 #endif | 165 #endif |
164 } | 166 } |
165 | 167 |
166 #if defined(OS_POSIX) | 168 #if defined(OS_POSIX) |
167 // See comment in BrowserMain, where sigaction is called. | 169 // See comment in BrowserMain, where sigaction is called. |
168 void SIGCHLDHandler(int signal) { | 170 void SIGCHLDHandler(int signal) { |
169 } | 171 } |
170 | 172 |
173 int g_shutdown_pipe_write_fd = -1; | |
174 int g_shutdown_pipe_read_fd = -1; | |
175 | |
171 // Common code between SIG{HUP, INT, TERM}Handler. | 176 // Common code between SIG{HUP, INT, TERM}Handler. |
172 void GracefulShutdownHandler(int signal, const int expected_signal) { | 177 void GracefulShutdownHandler(int signal) { |
173 DCHECK_EQ(signal, expected_signal); | |
174 LOG(INFO) << "Addressing signal " << expected_signal << " on " | |
175 << PlatformThread::CurrentId(); | |
176 | |
177 bool posted = ChromeThread::PostTask( | |
178 ChromeThread::UI, FROM_HERE, | |
179 NewRunnableFunction(BrowserList::CloseAllBrowsersAndExit)); | |
180 | |
181 // Reinstall the default handler. We had one shot at graceful shutdown. | 178 // Reinstall the default handler. We had one shot at graceful shutdown. |
182 struct sigaction action; | 179 struct sigaction action; |
183 memset(&action, 0, sizeof(action)); | 180 memset(&action, 0, sizeof(action)); |
184 action.sa_handler = SIG_DFL; | 181 action.sa_handler = SIG_DFL; |
185 CHECK(sigaction(expected_signal, &action, NULL) == 0); | 182 CHECK(sigaction(signal, &action, NULL) == 0); |
186 | 183 |
187 if (posted) { | 184 RAW_CHECK(g_shutdown_pipe_write_fd != -1); |
188 LOG(INFO) << "Posted task to UI thread; resetting signal " | 185 RAW_CHECK(g_shutdown_pipe_read_fd != -1); |
189 << expected_signal << " handler"; | 186 size_t bytes_written = 0; |
190 } else { | 187 do { |
188 int rv = HANDLE_EINTR( | |
189 write(g_shutdown_pipe_write_fd, | |
190 reinterpret_cast<const char*>(&signal) + bytes_written, | |
191 sizeof(signal) - bytes_written)); | |
192 RAW_CHECK(rv >= 0); | |
193 bytes_written += rv; | |
194 } while (bytes_written < sizeof(signal)); | |
195 | |
196 RAW_LOG(INFO, | |
197 "Successfully wrote to shutdown pipe, resetting signal handler."); | |
198 } | |
199 | |
200 // See comment in BrowserMain, where sigaction is called. | |
201 void SIGHUPHandler(int signal) { | |
202 RAW_CHECK(signal == SIGHUP); | |
203 RAW_LOG(INFO, "Handling SIGHUP."); | |
204 GracefulShutdownHandler(signal); | |
205 } | |
206 | |
207 // See comment in BrowserMain, where sigaction is called. | |
208 void SIGINTHandler(int signal) { | |
209 RAW_CHECK(signal == SIGINT); | |
210 RAW_LOG(INFO, "Handling SIGINT."); | |
211 GracefulShutdownHandler(signal); | |
212 } | |
213 | |
214 // See comment in BrowserMain, where sigaction is called. | |
215 void SIGTERMHandler(int signal) { | |
216 RAW_CHECK(signal == SIGTERM); | |
217 RAW_LOG(INFO, "Handling SIGTERM."); | |
218 GracefulShutdownHandler(signal); | |
219 } | |
220 | |
221 class ShutdownDetector : public PlatformThread::Delegate { | |
222 public: | |
223 explicit ShutdownDetector(int shutdown_fd); | |
224 | |
225 virtual void ThreadMain(); | |
226 | |
227 private: | |
228 const int shutdown_fd_; | |
229 | |
230 DISALLOW_COPY_AND_ASSIGN(ShutdownDetector); | |
231 }; | |
232 | |
233 ShutdownDetector::ShutdownDetector(int shutdown_fd) | |
234 : shutdown_fd_(shutdown_fd) { | |
235 CHECK(shutdown_fd_ != -1); | |
236 } | |
237 | |
238 void ShutdownDetector::ThreadMain() { | |
239 int signal; | |
240 size_t bytes_read = 0; | |
241 ssize_t ret; | |
242 do { | |
243 ret = HANDLE_EINTR( | |
244 read(shutdown_fd_, | |
245 reinterpret_cast<char*>(&signal) + bytes_read, | |
246 sizeof(signal) - bytes_read)); | |
247 if (ret < 0) { | |
248 NOTREACHED() << "Unexpected error: " << strerror(errno); | |
249 break; | |
250 } else if (ret == 0) { | |
251 NOTREACHED() << "Unexpected closure of shutdown pipe."; | |
252 break; | |
253 } | |
254 bytes_read += ret; | |
255 } while (bytes_read < sizeof(signal)); | |
256 | |
257 LOG(INFO) << "Handling shutdown for signal " << signal << "."; | |
258 | |
259 if (!ChromeThread::PostTask( | |
260 ChromeThread::UI, FROM_HERE, | |
261 NewRunnableFunction(BrowserList::CloseAllBrowsersAndExit))) { | |
191 // Without a UI thread to post the exit task to, there aren't many | 262 // Without a UI thread to post the exit task to, there aren't many |
192 // options. Raise the signal again. The default handler will pick it up | 263 // options. Raise the signal again. The default handler will pick it up |
193 // and cause an ungraceful exit. | 264 // and cause an ungraceful exit. |
194 LOG(WARNING) << "No UI thread, exiting ungracefully"; | 265 LOG(WARNING) << "No UI thread, exiting ungracefully."; |
195 kill(getpid(), signal); | 266 kill(getpid(), signal); |
196 | 267 |
197 // The signal may be handled on another thread. Give that a chance to | 268 // The signal may be handled on another thread. Give that a chance to |
198 // happen. | 269 // happen. |
199 sleep(3); | 270 sleep(3); |
200 | 271 |
201 // We really should be dead by now. For whatever reason, we're not. Exit | 272 // We really should be dead by now. For whatever reason, we're not. Exit |
202 // immediately, with the exit status set to the signal number with bit 8 | 273 // immediately, with the exit status set to the signal number with bit 8 |
203 // set. On the systems that we care about, this exit status is what is | 274 // set. On the systems that we care about, this exit status is what is |
204 // normally used to indicate an exit by this signal's default handler. | 275 // normally used to indicate an exit by this signal's default handler. |
205 // This mechanism isn't a de jure standard, but even in the worst case, it | 276 // This mechanism isn't a de jure standard, but even in the worst case, it |
206 // should at least result in an immediate exit. | 277 // should at least result in an immediate exit. |
207 LOG(WARNING) << "Still here, exiting really ungracefully"; | 278 LOG(WARNING) << "Still here, exiting really ungracefully."; |
208 _exit(signal | (1 << 7)); | 279 _exit(signal | (1 << 7)); |
209 } | 280 } |
210 } | 281 } |
211 | 282 |
212 // See comment in BrowserMain, where sigaction is called. | |
213 void SIGHUPHandler(int signal) { | |
214 GracefulShutdownHandler(signal, SIGHUP); | |
215 } | |
216 | |
217 // See comment in BrowserMain, where sigaction is called. | |
218 void SIGINTHandler(int signal) { | |
219 GracefulShutdownHandler(signal, SIGINT); | |
220 } | |
221 | |
222 // See comment in BrowserMain, where sigaction is called. | |
223 void SIGTERMHandler(int signal) { | |
224 GracefulShutdownHandler(signal, SIGTERM); | |
225 } | |
226 | |
227 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard | 283 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard |
228 // limit, whichever is lower. | 284 // limit, whichever is lower. |
229 void SetFileDescriptorLimit(unsigned int max_descriptors) { | 285 void SetFileDescriptorLimit(unsigned int max_descriptors) { |
230 struct rlimit limits; | 286 struct rlimit limits; |
231 if (getrlimit(RLIMIT_NOFILE, &limits) == 0) { | 287 if (getrlimit(RLIMIT_NOFILE, &limits) == 0) { |
232 unsigned int new_limit = max_descriptors; | 288 unsigned int new_limit = max_descriptors; |
233 if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) { | 289 if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) { |
234 new_limit = limits.rlim_max; | 290 new_limit = limits.rlim_max; |
235 } | 291 } |
236 limits.rlim_cur = new_limit; | 292 limits.rlim_cur = new_limit; |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
355 std::wstring app_name = chrome::kBrowserAppName; | 411 std::wstring app_name = chrome::kBrowserAppName; |
356 std::string thread_name_string = WideToASCII(app_name + L"_BrowserMain"); | 412 std::string thread_name_string = WideToASCII(app_name + L"_BrowserMain"); |
357 | 413 |
358 const char* thread_name = thread_name_string.c_str(); | 414 const char* thread_name = thread_name_string.c_str(); |
359 PlatformThread::SetName(thread_name); | 415 PlatformThread::SetName(thread_name); |
360 main_message_loop.set_thread_name(thread_name); | 416 main_message_loop.set_thread_name(thread_name); |
361 | 417 |
362 // Register the main thread by instantiating it, but don't call any methods. | 418 // Register the main thread by instantiating it, but don't call any methods. |
363 ChromeThread main_thread(ChromeThread::UI, MessageLoop::current()); | 419 ChromeThread main_thread(ChromeThread::UI, MessageLoop::current()); |
364 | 420 |
421 #if defined(OS_POSIX) | |
422 int pipefd[2]; | |
423 int ret = pipe(pipefd); | |
424 if (ret < 0) { | |
425 PLOG(DFATAL) << "Failed to create pipe"; | |
426 } else { | |
427 g_shutdown_pipe_read_fd = pipefd[0]; | |
428 g_shutdown_pipe_write_fd = pipefd[1]; | |
429 const size_t kShutdownDetectorThreadStackSize = 4096; | |
430 if (!PlatformThread::CreateNonJoinable( | |
431 kShutdownDetectorThreadStackSize, | |
432 new ShutdownDetector(g_shutdown_pipe_read_fd))) { | |
Hironori Bono
2009/12/08 09:44:53
I'm wondering when this ShutdownDetector instance
| |
433 LOG(DFATAL) << "Failed to create shutdown detector task."; | |
434 } | |
435 } | |
436 #endif // defined(OS_POSIX) | |
437 | |
365 FilePath user_data_dir; | 438 FilePath user_data_dir; |
366 #if defined(OS_WIN) | 439 #if defined(OS_WIN) |
367 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); | 440 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); |
368 #else | 441 #else |
369 // Getting the user data dir can fail if the directory isn't | 442 // Getting the user data dir can fail if the directory isn't |
370 // creatable, for example; on Windows in code below we bring up a | 443 // creatable, for example; on Windows in code below we bring up a |
371 // dialog prompting the user to pick a different directory. | 444 // dialog prompting the user to pick a different directory. |
372 // However, ProcessSingleton needs a real user_data_dir on Mac/Linux, | 445 // However, ProcessSingleton needs a real user_data_dir on Mac/Linux, |
373 // so it's better to fail here than fail mysteriously elsewhere. | 446 // so it's better to fail here than fail mysteriously elsewhere. |
374 CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) | 447 CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) |
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
898 if (metrics) | 971 if (metrics) |
899 metrics->Stop(); | 972 metrics->Stop(); |
900 | 973 |
901 // browser_shutdown takes care of deleting browser_process, so we need to | 974 // browser_shutdown takes care of deleting browser_process, so we need to |
902 // release it. | 975 // release it. |
903 browser_process.release(); | 976 browser_process.release(); |
904 browser_shutdown::Shutdown(); | 977 browser_shutdown::Shutdown(); |
905 | 978 |
906 return result_code; | 979 return result_code; |
907 } | 980 } |
OLD | NEW |