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

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

Issue 505068: Take 2: Re-enable TCMalloc on Linux and make POSIX signal handling async signal safe. (Closed)
Patch Set: Created 11 years 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
« no previous file with comments | « build/common.gypi ('k') | no next file » | 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) 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
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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 #elif defined(OS_POSIX) 164 #elif defined(OS_POSIX)
163 MessageLoopForUI::current()->Run(); 165 MessageLoopForUI::current()->Run();
164 #endif 166 #endif
165 } 167 }
166 168
167 #if defined(OS_POSIX) 169 #if defined(OS_POSIX)
168 // See comment in BrowserMain, where sigaction is called. 170 // See comment in BrowserMain, where sigaction is called.
169 void SIGCHLDHandler(int signal) { 171 void SIGCHLDHandler(int signal) {
170 } 172 }
171 173
174 int g_shutdown_pipe_write_fd = -1;
175 int g_shutdown_pipe_read_fd = -1;
176
172 // Common code between SIG{HUP, INT, TERM}Handler. 177 // Common code between SIG{HUP, INT, TERM}Handler.
173 void GracefulShutdownHandler(int signal, const int expected_signal) { 178 void GracefulShutdownHandler(int signal) {
174 DCHECK_EQ(signal, expected_signal);
175 LOG(INFO) << "Addressing signal " << expected_signal << " on "
176 << PlatformThread::CurrentId();
177
178 bool posted = ChromeThread::PostTask(
179 ChromeThread::UI, FROM_HERE,
180 NewRunnableFunction(BrowserList::CloseAllBrowsersAndExit));
181
182 // Reinstall the default handler. We had one shot at graceful shutdown. 179 // Reinstall the default handler. We had one shot at graceful shutdown.
183 struct sigaction action; 180 struct sigaction action;
184 memset(&action, 0, sizeof(action)); 181 memset(&action, 0, sizeof(action));
185 action.sa_handler = SIG_DFL; 182 action.sa_handler = SIG_DFL;
186 CHECK(sigaction(expected_signal, &action, NULL) == 0); 183 CHECK(sigaction(signal, &action, NULL) == 0);
187 184
188 if (posted) { 185 RAW_CHECK(g_shutdown_pipe_write_fd != -1);
189 LOG(INFO) << "Posted task to UI thread; resetting signal " 186 RAW_CHECK(g_shutdown_pipe_read_fd != -1);
190 << expected_signal << " handler"; 187 size_t bytes_written = 0;
191 } else { 188 do {
189 int rv = HANDLE_EINTR(
190 write(g_shutdown_pipe_write_fd,
191 reinterpret_cast<const char*>(&signal) + bytes_written,
192 sizeof(signal) - bytes_written));
193 RAW_CHECK(rv >= 0);
194 bytes_written += rv;
195 } while (bytes_written < sizeof(signal));
196
197 RAW_LOG(INFO,
198 "Successfully wrote to shutdown pipe, resetting signal handler.");
199 }
200
201 // See comment in BrowserMain, where sigaction is called.
202 void SIGHUPHandler(int signal) {
203 RAW_CHECK(signal == SIGHUP);
204 RAW_LOG(INFO, "Handling SIGHUP.");
205 GracefulShutdownHandler(signal);
206 }
207
208 // See comment in BrowserMain, where sigaction is called.
209 void SIGINTHandler(int signal) {
210 RAW_CHECK(signal == SIGINT);
211 RAW_LOG(INFO, "Handling SIGINT.");
212 GracefulShutdownHandler(signal);
213 }
214
215 // See comment in BrowserMain, where sigaction is called.
216 void SIGTERMHandler(int signal) {
217 RAW_CHECK(signal == SIGTERM);
218 RAW_LOG(INFO, "Handling SIGTERM.");
219 GracefulShutdownHandler(signal);
220 }
221
222 class ShutdownDetector : public PlatformThread::Delegate {
223 public:
224 explicit ShutdownDetector(int shutdown_fd);
225
226 virtual void ThreadMain();
227
228 private:
229 const int shutdown_fd_;
230
231 DISALLOW_COPY_AND_ASSIGN(ShutdownDetector);
232 };
233
234 ShutdownDetector::ShutdownDetector(int shutdown_fd)
235 : shutdown_fd_(shutdown_fd) {
236 CHECK(shutdown_fd_ != -1);
237 }
238
239 void ShutdownDetector::ThreadMain() {
240 int signal;
241 size_t bytes_read = 0;
242 ssize_t ret;
243 do {
244 ret = HANDLE_EINTR(
245 read(shutdown_fd_,
246 reinterpret_cast<char*>(&signal) + bytes_read,
247 sizeof(signal) - bytes_read));
248 if (ret < 0) {
249 NOTREACHED() << "Unexpected error: " << strerror(errno);
250 break;
251 } else if (ret == 0) {
252 NOTREACHED() << "Unexpected closure of shutdown pipe.";
253 break;
254 }
255 bytes_read += ret;
256 } while (bytes_read < sizeof(signal));
257
258 LOG(INFO) << "Handling shutdown for signal " << signal << ".";
259
260 if (!ChromeThread::PostTask(
261 ChromeThread::UI, FROM_HERE,
262 NewRunnableFunction(BrowserList::CloseAllBrowsersAndExit))) {
192 // Without a UI thread to post the exit task to, there aren't many 263 // Without a UI thread to post the exit task to, there aren't many
193 // options. Raise the signal again. The default handler will pick it up 264 // options. Raise the signal again. The default handler will pick it up
194 // and cause an ungraceful exit. 265 // and cause an ungraceful exit.
195 LOG(WARNING) << "No UI thread, exiting ungracefully"; 266 LOG(WARNING) << "No UI thread, exiting ungracefully.";
196 kill(getpid(), signal); 267 kill(getpid(), signal);
197 268
198 // The signal may be handled on another thread. Give that a chance to 269 // The signal may be handled on another thread. Give that a chance to
199 // happen. 270 // happen.
200 sleep(3); 271 sleep(3);
201 272
202 // We really should be dead by now. For whatever reason, we're not. Exit 273 // We really should be dead by now. For whatever reason, we're not. Exit
203 // immediately, with the exit status set to the signal number with bit 8 274 // immediately, with the exit status set to the signal number with bit 8
204 // set. On the systems that we care about, this exit status is what is 275 // set. On the systems that we care about, this exit status is what is
205 // normally used to indicate an exit by this signal's default handler. 276 // normally used to indicate an exit by this signal's default handler.
206 // This mechanism isn't a de jure standard, but even in the worst case, it 277 // This mechanism isn't a de jure standard, but even in the worst case, it
207 // should at least result in an immediate exit. 278 // should at least result in an immediate exit.
208 LOG(WARNING) << "Still here, exiting really ungracefully"; 279 LOG(WARNING) << "Still here, exiting really ungracefully.";
209 _exit(signal | (1 << 7)); 280 _exit(signal | (1 << 7));
210 } 281 }
211 } 282 }
212 283
213 // See comment in BrowserMain, where sigaction is called.
214 void SIGHUPHandler(int signal) {
215 GracefulShutdownHandler(signal, SIGHUP);
216 }
217
218 // See comment in BrowserMain, where sigaction is called.
219 void SIGINTHandler(int signal) {
220 GracefulShutdownHandler(signal, SIGINT);
221 }
222
223 // See comment in BrowserMain, where sigaction is called.
224 void SIGTERMHandler(int signal) {
225 GracefulShutdownHandler(signal, SIGTERM);
226 }
227
228 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard 284 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard
229 // limit, whichever is lower. 285 // limit, whichever is lower.
230 void SetFileDescriptorLimit(unsigned int max_descriptors) { 286 void SetFileDescriptorLimit(unsigned int max_descriptors) {
231 struct rlimit limits; 287 struct rlimit limits;
232 if (getrlimit(RLIMIT_NOFILE, &limits) == 0) { 288 if (getrlimit(RLIMIT_NOFILE, &limits) == 0) {
233 unsigned int new_limit = max_descriptors; 289 unsigned int new_limit = max_descriptors;
234 if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) { 290 if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) {
235 new_limit = limits.rlim_max; 291 new_limit = limits.rlim_max;
236 } 292 }
237 limits.rlim_cur = new_limit; 293 limits.rlim_cur = new_limit;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 std::wstring app_name = chrome::kBrowserAppName; 412 std::wstring app_name = chrome::kBrowserAppName;
357 std::string thread_name_string = WideToASCII(app_name + L"_BrowserMain"); 413 std::string thread_name_string = WideToASCII(app_name + L"_BrowserMain");
358 414
359 const char* thread_name = thread_name_string.c_str(); 415 const char* thread_name = thread_name_string.c_str();
360 PlatformThread::SetName(thread_name); 416 PlatformThread::SetName(thread_name);
361 main_message_loop.set_thread_name(thread_name); 417 main_message_loop.set_thread_name(thread_name);
362 418
363 // Register the main thread by instantiating it, but don't call any methods. 419 // Register the main thread by instantiating it, but don't call any methods.
364 ChromeThread main_thread(ChromeThread::UI, MessageLoop::current()); 420 ChromeThread main_thread(ChromeThread::UI, MessageLoop::current());
365 421
422 #if defined(OS_POSIX)
423 int pipefd[2];
424 int ret = pipe(pipefd);
425 if (ret < 0) {
426 PLOG(DFATAL) << "Failed to create pipe";
427 } else {
428 g_shutdown_pipe_read_fd = pipefd[0];
429 g_shutdown_pipe_write_fd = pipefd[1];
430 const size_t kShutdownDetectorThreadStackSize = 4096;
431 if (!PlatformThread::CreateNonJoinable(
432 kShutdownDetectorThreadStackSize,
433 new ShutdownDetector(g_shutdown_pipe_read_fd))) {
434 LOG(DFATAL) << "Failed to create shutdown detector task.";
435 }
436 }
437 #endif // defined(OS_POSIX)
438
366 FilePath user_data_dir; 439 FilePath user_data_dir;
367 #if defined(OS_WIN) 440 #if defined(OS_WIN)
368 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); 441 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
369 #else 442 #else
370 // Getting the user data dir can fail if the directory isn't 443 // Getting the user data dir can fail if the directory isn't
371 // creatable, for example; on Windows in code below we bring up a 444 // creatable, for example; on Windows in code below we bring up a
372 // dialog prompting the user to pick a different directory. 445 // dialog prompting the user to pick a different directory.
373 // However, ProcessSingleton needs a real user_data_dir on Mac/Linux, 446 // However, ProcessSingleton needs a real user_data_dir on Mac/Linux,
374 // so it's better to fail here than fail mysteriously elsewhere. 447 // so it's better to fail here than fail mysteriously elsewhere.
375 CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) 448 CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after
919 if (metrics) 992 if (metrics)
920 metrics->Stop(); 993 metrics->Stop();
921 994
922 // browser_shutdown takes care of deleting browser_process, so we need to 995 // browser_shutdown takes care of deleting browser_process, so we need to
923 // release it. 996 // release it.
924 browser_process.release(); 997 browser_process.release();
925 browser_shutdown::Shutdown(); 998 browser_shutdown::Shutdown();
926 999
927 return result_code; 1000 return result_code;
928 } 1001 }
OLDNEW
« no previous file with comments | « build/common.gypi ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698