summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-09 15:35:47 +0000
committerpinkerton@chromium.org <pinkerton@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-09 15:35:47 +0000
commit7c32108b22446be27129324ce41d32e9c909e379 (patch)
tree2b18444c829ae9155036ef3c55ab1fb645b9621e
parent54131d25aa7e887f89ba25851b983150cd1384a8 (diff)
downloadchromium_src-7c32108b22446be27129324ce41d32e9c909e379.zip
chromium_src-7c32108b22446be27129324ce41d32e9c909e379.tar.gz
chromium_src-7c32108b22446be27129324ce41d32e9c909e379.tar.bz2
Add Recycle() method to scoped autorelease pool to allow cleaning out any junk
created at startup before the main runloop. Correct quit on Mac to let the BrowserProcess shut down the event loop when its refcount goes to zero after cleaning up all browser windows. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9386 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/scoped_nsautorelease_pool.h6
-rw-r--r--base/scoped_nsautorelease_pool.mm11
-rw-r--r--chrome/app/chrome_dll_main.cc12
-rw-r--r--chrome/browser/app_controller_mac.mm21
-rw-r--r--chrome/browser/browser_main.cc7
-rw-r--r--chrome/browser/browser_window_cocoa.mm1
-rw-r--r--chrome/common/main_function_params.h10
-rw-r--r--chrome/renderer/renderer_main.cc3
-rw-r--r--chrome/renderer/renderer_main_unittest.cc3
-rw-r--r--chrome/test/in_process_browser_test.cc2
10 files changed, 57 insertions, 19 deletions
diff --git a/base/scoped_nsautorelease_pool.h b/base/scoped_nsautorelease_pool.h
index 0e779af..64bf9e7 100644
--- a/base/scoped_nsautorelease_pool.h
+++ b/base/scoped_nsautorelease_pool.h
@@ -29,10 +29,16 @@ class ScopedNSAutoreleasePool {
public:
#if !defined(OS_MACOSX)
ScopedNSAutoreleasePool() {}
+ void Recycle() { }
#else // OS_MACOSX
ScopedNSAutoreleasePool();
~ScopedNSAutoreleasePool();
+ // Clear out the pool in case its position on the stack causes it to be
+ // alive for long periods of time (such as the entire length of the app).
+ // Only use then when you're certain the items currently in the pool are
+ // no longer needed.
+ void Recycle();
private:
NSAutoreleasePool* autorelease_pool_;
#endif // OS_MACOSX
diff --git a/base/scoped_nsautorelease_pool.mm b/base/scoped_nsautorelease_pool.mm
index c4ae517..174fb82 100644
--- a/base/scoped_nsautorelease_pool.mm
+++ b/base/scoped_nsautorelease_pool.mm
@@ -6,14 +6,25 @@
#import <Foundation/Foundation.h>
+#include "base/logging.h"
+
namespace base {
ScopedNSAutoreleasePool::ScopedNSAutoreleasePool()
: autorelease_pool_([[NSAutoreleasePool alloc] init]) {
+ DCHECK(autorelease_pool_);
}
ScopedNSAutoreleasePool::~ScopedNSAutoreleasePool() {
[autorelease_pool_ drain];
}
+// Cycle the internal pool, allowing everything there to get cleaned up and
+// start anew.
+void ScopedNSAutoreleasePool::Recycle() {
+ [autorelease_pool_ drain];
+ autorelease_pool_ = [[NSAutoreleasePool alloc] init];
+ DCHECK(autorelease_pool_);
+}
+
} // namespace base
diff --git a/chrome/app/chrome_dll_main.cc b/chrome/app/chrome_dll_main.cc
index ebde279..f14b886 100644
--- a/chrome/app/chrome_dll_main.cc
+++ b/chrome/app/chrome_dll_main.cc
@@ -200,11 +200,10 @@ int ChromeMain(int argc, const char** argv) {
// The exit manager is in charge of calling the dtors of singleton objects.
base::AtExitManager exit_manager;
- // TODO(pinkerton): We need this pool here for all the objects created
- // before we get to the UI event loop, but we don't want to leave them
- // hanging around until the app quits. We should add a "flush" to the class
- // which just cycles the pool under the covers and then call that just
- // before we invoke the main UI loop near the bottom of this function.
+ // We need this pool for all the objects created before we get to the
+ // event loop, but we don't want to leave them hanging around until the
+ // app quits. Each "main" needs to flush this pool right before it goes into
+ // its main event loop to get rid of the cruft.
base::ScopedNSAutoreleasePool autorelease_pool;
#if defined(OS_LINUX)
@@ -307,7 +306,8 @@ int ChromeMain(int argc, const char** argv) {
startup_timer.Stop(); // End of Startup Time Measurement.
- MainFunctionParams main_params(parsed_command_line, sandbox_wrapper);
+ MainFunctionParams main_params(parsed_command_line, sandbox_wrapper,
+ &autorelease_pool);
// TODO(port): turn on these main() functions as they've been de-winified.
int rv = -1;
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm
index 3895ece..5a9609a 100644
--- a/chrome/browser/app_controller_mac.mm
+++ b/chrome/browser/app_controller_mac.mm
@@ -19,10 +19,18 @@
@implementation AppController
- (void)awakeFromNib {
- // set up the command updater for when there are no windows open
+ // Set up the command updater for when there are no windows open
[self initMenuState];
}
+- (void)applicationDidFinishLaunching:(NSNotification*)notify {
+ // Hold an extra ref to the BrowserProcess singleton so it doesn't go away
+ // when all the browser windows get closed. We'll release it on quit which
+ // will be the signal to exit.
+ DCHECK(g_browser_process);
+ g_browser_process->AddRefModule();
+}
+
- (void)dealloc {
delete menuState_;
[super dealloc];
@@ -41,14 +49,11 @@
// go back to normal.
// Close all the windows.
- // TODO(pinkerton): the close code assumes that teardown happens
- // synchronously, however with autorelease pools and ref-counting, we can't
- // guarantee the window controller hits 0 inside this call, and thus the
- // number of Browsers still alive will certainly be non-zero. Not sure yet
- // how to handle this case.
- // BrowserList::CloseAllBrowsers(false);
+ BrowserList::CloseAllBrowsers(true);
- MessageLoopForUI::current()->Quit();
+ // Release the reference to the browser process. Once all the browsers get
+ // dealloc'd, it will stop the RunLoop and fall back into main().
+ g_browser_process->ReleaseModule();
}
// Called to validate menu items when there are no key windows. All the
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc
index 23a8078..654da338 100644
--- a/chrome/browser/browser_main.cc
+++ b/chrome/browser/browser_main.cc
@@ -11,6 +11,7 @@
#include "base/file_util.h"
#include "base/histogram.h"
#include "base/lazy_instance.h"
+#include "base/scoped_nsautorelease_pool.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/string_piece.h"
@@ -190,6 +191,7 @@ void RunUIMessageLoop(BrowserProcess* browser_process) {
// Main routine for running as the Browser process.
int BrowserMain(const MainFunctionParams& parameters) {
const CommandLine& parsed_command_line = parameters.command_line_;
+ base::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool_;
// WARNING: If we get a WM_ENDSESSION objects created on the stack here
// are NOT deleted. If you need something to run during WM_ENDSESSION add it
@@ -554,13 +556,18 @@ int BrowserMain(const MainFunctionParams& parameters) {
// This should happen before ProcessCommandLine.
profile->InitExtensions();
+ // Call Recycle() here as late as possible, just before going into the main
+ // loop. We can't do it any earlier, as ProcessCommandLine() will add things
+ // to it in the act of creating the initial browser window.
int result_code = ResultCodes::NORMAL_EXIT;
if (parameters.ui_task) {
+ if (pool) pool->Recycle();
MessageLoopForUI::current()->PostTask(FROM_HERE, parameters.ui_task);
RunUIMessageLoop(browser_process.get());
} else if (BrowserInit::ProcessCommandLine(parsed_command_line,
std::wstring(), local_state, true,
profile, &result_code)) {
+ if (pool) pool->Recycle();
RunUIMessageLoop(browser_process.get());
}
diff --git a/chrome/browser/browser_window_cocoa.mm b/chrome/browser/browser_window_cocoa.mm
index b78b913..c541985 100644
--- a/chrome/browser/browser_window_cocoa.mm
+++ b/chrome/browser/browser_window_cocoa.mm
@@ -33,6 +33,7 @@ void BrowserWindowCocoa::SetBounds(const gfx::Rect& bounds) {
void BrowserWindowCocoa::Close() {
[window_ orderOut:controller_];
+ [window_ performClose:controller_];
}
void BrowserWindowCocoa::Activate() {
diff --git a/chrome/common/main_function_params.h b/chrome/common/main_function_params.h
index 5537879..1a240c5 100644
--- a/chrome/common/main_function_params.h
+++ b/chrome/common/main_function_params.h
@@ -12,13 +12,19 @@
#include "base/command_line.h"
#include "chrome/common/sandbox_init_wrapper.h"
+namespace base {
+class ScopedNSAutoreleasePool;
+};
class Task;
struct MainFunctionParams {
- MainFunctionParams(const CommandLine& cl, const SandboxInitWrapper& sb)
- : command_line_(cl), sandbox_info_(sb), ui_task(NULL) { }
+ MainFunctionParams(const CommandLine& cl, const SandboxInitWrapper& sb,
+ base::ScopedNSAutoreleasePool* pool)
+ : command_line_(cl), sandbox_info_(sb), autorelease_pool_(pool),
+ ui_task(NULL) { }
const CommandLine& command_line_;
const SandboxInitWrapper& sandbox_info_;
+ base::ScopedNSAutoreleasePool* autorelease_pool_;
// Used by InProcessBrowserTest. If non-null BrowserMain schedules this
// task to run on the MessageLoop and BrowserInit is not invoked.
Task* ui_task;
diff --git a/chrome/renderer/renderer_main.cc b/chrome/renderer/renderer_main.cc
index ff13fdb..561a9ef 100644
--- a/chrome/renderer/renderer_main.cc
+++ b/chrome/renderer/renderer_main.cc
@@ -6,6 +6,7 @@
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/platform_thread.h"
+#include "base/scoped_nsautorelease_pool.h"
#include "base/string_util.h"
#include "base/system_monitor.h"
#include "chrome/common/chrome_constants.h"
@@ -56,6 +57,7 @@ static void HandleRendererErrorTestParameters(const CommandLine& command_line) {
// mainline routine for running as the Rendererer process
int RendererMain(const MainFunctionParams& parameters) {
const CommandLine& parsed_command_line = parameters.command_line_;
+ base::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool_;
RendererMainPlatformDelegate platform(parameters);
StatsScope<StatsCounterTimer>
@@ -91,6 +93,7 @@ int RendererMain(const MainFunctionParams& parameters) {
if (run_loop) {
// Load the accelerator table from the browser executable and tell the
// message loop to use it when translating messages.
+ if (pool) pool->Recycle();
MessageLoop::current()->Run();
}
diff --git a/chrome/renderer/renderer_main_unittest.cc b/chrome/renderer/renderer_main_unittest.cc
index f94c844..c938f5b 100644
--- a/chrome/renderer/renderer_main_unittest.cc
+++ b/chrome/renderer/renderer_main_unittest.cc
@@ -82,8 +82,7 @@ MULTIPROCESS_TEST_MAIN(SimpleRenderer) {
cl.AppendSwitchWithValue(switches::kProcessChannelID,
kRendererTestChannelName);
- MainFunctionParams dummy_params(cl,
- dummy_sandbox_init);
+ MainFunctionParams dummy_params(cl, dummy_sandbox_init, NULL);
return RendererMain(dummy_params);
}
diff --git a/chrome/test/in_process_browser_test.cc b/chrome/test/in_process_browser_test.cc
index 6d6cc96..dd1f919 100644
--- a/chrome/test/in_process_browser_test.cc
+++ b/chrome/test/in_process_browser_test.cc
@@ -88,7 +88,7 @@ void InProcessBrowserTest::SetUp() {
sandbox::SandboxInterfaceInfo sandbox_info = {0};
SandboxInitWrapper sandbox_wrapper;
- MainFunctionParams params(*command_line, sandbox_wrapper);
+ MainFunctionParams params(*command_line, sandbox_wrapper, NULL);
params.ui_task =
NewRunnableMethod(this, &InProcessBrowserTest::RunTestOnMainThreadLoop);
BrowserMain(params);