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

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

Issue 460144: Fix leak of ShutdownDetector. (Closed)
Patch Set: Addressed Mark's comments. 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 | « no previous file | tools/valgrind/memcheck/suppressions.txt » ('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) 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"
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 MessageLoopForUI::current()->Run(); 164 MessageLoopForUI::current()->Run();
165 #endif 165 #endif
166 } 166 }
167 167
168 #if defined(OS_POSIX) 168 #if defined(OS_POSIX)
169 // See comment in BrowserMain, where sigaction is called. 169 // See comment in BrowserMain, where sigaction is called.
170 void SIGCHLDHandler(int signal) { 170 void SIGCHLDHandler(int signal) {
171 } 171 }
172 172
173 int g_shutdown_pipe_write_fd = -1; 173 int g_shutdown_pipe_write_fd = -1;
174 int g_shutdown_pipe_read_fd = -1;
175 174
176 // Common code between SIG{HUP, INT, TERM}Handler. 175 // Common code between SIG{HUP, INT, TERM}Handler.
177 void GracefulShutdownHandler(int signal) { 176 void GracefulShutdownHandler(int signal) {
178 // Reinstall the default handler. We had one shot at graceful shutdown. 177 // Reinstall the default handler. We had one shot at graceful shutdown.
179 struct sigaction action; 178 struct sigaction action;
180 memset(&action, 0, sizeof(action)); 179 memset(&action, 0, sizeof(action));
181 action.sa_handler = SIG_DFL; 180 action.sa_handler = SIG_DFL;
182 CHECK(sigaction(signal, &action, NULL) == 0); 181 CHECK(sigaction(signal, &action, NULL) == 0);
183 182
184 RAW_CHECK(g_shutdown_pipe_write_fd != -1); 183 RAW_CHECK(g_shutdown_pipe_write_fd != -1);
185 RAW_CHECK(g_shutdown_pipe_read_fd != -1);
186 size_t bytes_written = 0; 184 size_t bytes_written = 0;
187 do { 185 do {
188 int rv = HANDLE_EINTR( 186 int rv = HANDLE_EINTR(
189 write(g_shutdown_pipe_write_fd, 187 write(g_shutdown_pipe_write_fd,
190 reinterpret_cast<const char*>(&signal) + bytes_written, 188 reinterpret_cast<const char*>(&signal) + bytes_written,
191 sizeof(signal) - bytes_written)); 189 sizeof(signal) - bytes_written));
192 RAW_CHECK(rv >= 0); 190 RAW_CHECK(rv >= 0);
193 bytes_written += rv; 191 bytes_written += rv;
194 } while (bytes_written < sizeof(signal)); 192 } while (bytes_written < sizeof(signal));
195 193
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 ssize_t ret; 239 ssize_t ret;
242 do { 240 do {
243 ret = HANDLE_EINTR( 241 ret = HANDLE_EINTR(
244 read(shutdown_fd_, 242 read(shutdown_fd_,
245 reinterpret_cast<char*>(&signal) + bytes_read, 243 reinterpret_cast<char*>(&signal) + bytes_read,
246 sizeof(signal) - bytes_read)); 244 sizeof(signal) - bytes_read));
247 if (ret < 0) { 245 if (ret < 0) {
248 NOTREACHED() << "Unexpected error: " << strerror(errno); 246 NOTREACHED() << "Unexpected error: " << strerror(errno);
249 break; 247 break;
250 } else if (ret == 0) { 248 } else if (ret == 0) {
251 NOTREACHED() << "Unexpected closure of shutdown pipe."; 249 // Normal shutdown.
252 break; 250 break;
253 } 251 }
254 bytes_read += ret; 252 bytes_read += ret;
255 } while (bytes_read < sizeof(signal)); 253 } while (bytes_read < sizeof(signal));
256 254
257 LOG(INFO) << "Handling shutdown for signal " << signal << "."; 255 if (bytes_read == sizeof(signal)) {
256 LOG(INFO) << "Handling shutdown for signal " << signal << ".";
258 257
259 if (!ChromeThread::PostTask( 258 if (!ChromeThread::PostTask(
260 ChromeThread::UI, FROM_HERE, 259 ChromeThread::UI, FROM_HERE,
261 NewRunnableFunction(BrowserList::CloseAllBrowsersAndExit))) { 260 NewRunnableFunction(BrowserList::CloseAllBrowsersAndExit))) {
262 // Without a UI thread to post the exit task to, there aren't many 261 // Without a UI thread to post the exit task to, there aren't many
263 // options. Raise the signal again. The default handler will pick it up 262 // options. Raise the signal again. The default handler will pick it up
264 // and cause an ungraceful exit. 263 // and cause an ungraceful exit.
265 LOG(WARNING) << "No UI thread, exiting ungracefully."; 264 LOG(WARNING) << "No UI thread, exiting ungracefully.";
266 kill(getpid(), signal); 265 PLOG_IF(ERROR, raise(signal) != 0) << "Failed to raise signal";
267 266
268 // The signal may be handled on another thread. Give that a chance to 267 // The signal may be handled on another thread. Give that a chance to
269 // happen. 268 // happen.
270 sleep(3); 269 sleep(3);
271 270
272 // We really should be dead by now. For whatever reason, we're not. Exit 271 // We really should be dead by now. For whatever reason, we're not. Exit
273 // immediately, with the exit status set to the signal number with bit 8 272 // immediately, with the exit status set to the signal number with bit 8
274 // set. On the systems that we care about, this exit status is what is 273 // set. On the systems that we care about, this exit status is what is
275 // normally used to indicate an exit by this signal's default handler. 274 // normally used to indicate an exit by this signal's default handler.
276 // This mechanism isn't a de jure standard, but even in the worst case, it 275 // This mechanism isn't a de jure standard, but even in the worst case, it
277 // should at least result in an immediate exit. 276 // should at least result in an immediate exit.
278 LOG(WARNING) << "Still here, exiting really ungracefully."; 277 LOG(WARNING) << "Still here, exiting really ungracefully.";
279 _exit(signal | (1 << 7)); 278 _exit(signal | (1 << 7));
279 }
280 } 280 }
281
282 delete this;
281 } 283 }
282 284
283 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard 285 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard
284 // limit, whichever is lower. 286 // limit, whichever is lower.
285 void SetFileDescriptorLimit(unsigned int max_descriptors) { 287 void SetFileDescriptorLimit(unsigned int max_descriptors) {
286 struct rlimit limits; 288 struct rlimit limits;
287 if (getrlimit(RLIMIT_NOFILE, &limits) == 0) { 289 if (getrlimit(RLIMIT_NOFILE, &limits) == 0) {
288 unsigned int new_limit = max_descriptors; 290 unsigned int new_limit = max_descriptors;
289 if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) { 291 if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) {
290 new_limit = limits.rlim_max; 292 new_limit = limits.rlim_max;
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 const char* thread_name = thread_name_string.c_str(); 416 const char* thread_name = thread_name_string.c_str();
415 PlatformThread::SetName(thread_name); 417 PlatformThread::SetName(thread_name);
416 main_message_loop.set_thread_name(thread_name); 418 main_message_loop.set_thread_name(thread_name);
417 419
418 // Register the main thread by instantiating it, but don't call any methods. 420 // Register the main thread by instantiating it, but don't call any methods.
419 ChromeThread main_thread(ChromeThread::UI, MessageLoop::current()); 421 ChromeThread main_thread(ChromeThread::UI, MessageLoop::current());
420 422
421 #if defined(OS_POSIX) 423 #if defined(OS_POSIX)
422 int pipefd[2]; 424 int pipefd[2];
423 int ret = pipe(pipefd); 425 int ret = pipe(pipefd);
426 PlatformThreadHandle shutdown_detector_thread;
424 if (ret < 0) { 427 if (ret < 0) {
425 PLOG(DFATAL) << "Failed to create pipe"; 428 PLOG(DFATAL) << "Failed to create pipe";
426 } else { 429 } else {
427 g_shutdown_pipe_read_fd = pipefd[0];
428 g_shutdown_pipe_write_fd = pipefd[1];
429 const size_t kShutdownDetectorThreadStackSize = 4096; 430 const size_t kShutdownDetectorThreadStackSize = 4096;
430 if (!PlatformThread::CreateNonJoinable( 431 if (PlatformThread::Create(
431 kShutdownDetectorThreadStackSize, 432 kShutdownDetectorThreadStackSize,
432 new ShutdownDetector(g_shutdown_pipe_read_fd))) { 433 new ShutdownDetector(pipefd[0]),
434 &shutdown_detector_thread)) {
435 // Successfully spawned shutdown detector thread.
436 g_shutdown_pipe_write_fd = pipefd[1];
437 } else {
433 LOG(DFATAL) << "Failed to create shutdown detector task."; 438 LOG(DFATAL) << "Failed to create shutdown detector task.";
439 ret = HANDLE_EINTR(close(pipefd[0]));
440 PLOG_IF(ERROR, ret != 0) << "Failed to close shutdown read pipe";
441 ret = HANDLE_EINTR(close(pipefd[1]));
442 PLOG_IF(ERROR, ret != 0) << "Failed to close shutdown write pipe";
434 } 443 }
435 } 444 }
436 #endif // defined(OS_POSIX) 445 #endif // defined(OS_POSIX)
437 446
438 FilePath user_data_dir; 447 FilePath user_data_dir;
439 #if defined(OS_WIN) 448 #if defined(OS_WIN)
440 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); 449 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
441 #else 450 #else
442 // Getting the user data dir can fail if the directory isn't 451 // Getting the user data dir can fail if the directory isn't
443 // creatable, for example; on Windows in code below we bring up a 452 // creatable, for example; on Windows in code below we bring up a
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after
957 &result_code)) { 966 &result_code)) {
958 // Call Recycle() here as late as possible, before going into the loop 967 // Call Recycle() here as late as possible, before going into the loop
959 // because Start() will add things to it while creating the main window. 968 // because Start() will add things to it while creating the main window.
960 if (pool) 969 if (pool)
961 pool->Recycle(); 970 pool->Recycle();
962 RunUIMessageLoop(browser_process.get()); 971 RunUIMessageLoop(browser_process.get());
963 } 972 }
964 } 973 }
965 chrome_browser_net_websocket_experiment::WebSocketExperimentRunner::Stop(); 974 chrome_browser_net_websocket_experiment::WebSocketExperimentRunner::Stop();
966 975
976 #if defined(OS_POSIX)
977 // If we initialized the shutdown pipe, then close it.
978 if (g_shutdown_pipe_write_fd != -1) {
979 ret = HANDLE_EINTR(close(g_shutdown_pipe_write_fd));
980 g_shutdown_pipe_write_fd = -1;
981 PLOG_IF(ERROR, ret != 0) << "Failed to close";
982 }
983 #endif // defined(OS_POSIX)
984
967 process_singleton.Cleanup(); 985 process_singleton.Cleanup();
968 986
969 Platform::DidEndMainMessageLoop(); 987 Platform::DidEndMainMessageLoop();
970 988
971 if (metrics) 989 if (metrics)
972 metrics->Stop(); 990 metrics->Stop();
973 991
974 // browser_shutdown takes care of deleting browser_process, so we need to 992 // browser_shutdown takes care of deleting browser_process, so we need to
975 // release it. 993 // release it.
976 browser_process.release(); 994 browser_process.release();
977 browser_shutdown::Shutdown(); 995 browser_shutdown::Shutdown();
978 996
979 return result_code; 997 return result_code;
980 } 998 }
OLDNEW
« no previous file with comments | « no previous file | tools/valgrind/memcheck/suppressions.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698