Fix singleton relaunch issues with multi-threaded-message-loop (fixes #3635)
- Fix UI thread shutdown issues on early app exit. - views: cefclient: Fix threading requirements in RootWindowViews::Init when called on the UI thread via OnAlreadyRunningAppRelaunch.
This commit is contained in:
parent
c4cb1d9fb5
commit
ce31761f51
|
@ -181,12 +181,20 @@ class CefUIThread : public base::PlatformThread::Delegate {
|
||||||
|
|
||||||
runner_->RunMessageLoop();
|
runner_->RunMessageLoop();
|
||||||
|
|
||||||
|
// Stop may be called before InitializeBrowserRunner if
|
||||||
|
// content::ContentMainRun was not successful (for example, due to process
|
||||||
|
// singleton relaunch).
|
||||||
|
if (browser_runner_) {
|
||||||
browser_runner_->Shutdown();
|
browser_runner_->Shutdown();
|
||||||
browser_runner_.reset();
|
browser_runner_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will be a no-op if there is no BrowserTaskExecutor.
|
||||||
content::BrowserTaskExecutor::Shutdown();
|
content::BrowserTaskExecutor::Shutdown();
|
||||||
|
|
||||||
|
if (!shutdown_callback_.is_null()) {
|
||||||
std::move(shutdown_callback_).Run();
|
std::move(shutdown_callback_).Run();
|
||||||
|
}
|
||||||
|
|
||||||
// Run exit callbacks on the UI thread to avoid sequence check failures.
|
// Run exit callbacks on the UI thread to avoid sequence check failures.
|
||||||
base::AtExitManager::ProcessCallbacksNow();
|
base::AtExitManager::ProcessCallbacksNow();
|
||||||
|
@ -433,6 +441,11 @@ int CefMainRunner::ContentMainRun(bool* initialized,
|
||||||
int* exit_code) {
|
int* exit_code) {
|
||||||
runner->main_delegate_->BeforeUIThreadInitialize();
|
runner->main_delegate_->BeforeUIThreadInitialize();
|
||||||
*exit_code = content::ContentMainRun(runner->main_runner_.get());
|
*exit_code = content::ContentMainRun(runner->main_runner_.get());
|
||||||
|
|
||||||
|
if (*exit_code != content::RESULT_CODE_NORMAL_EXIT) {
|
||||||
|
runner->FinishShutdownOnUIThread();
|
||||||
|
}
|
||||||
|
|
||||||
event->Signal();
|
event->Signal();
|
||||||
},
|
},
|
||||||
base::Unretained(this), base::Unretained(&uithread_startup_event),
|
base::Unretained(this), base::Unretained(&uithread_startup_event),
|
||||||
|
@ -444,6 +457,13 @@ int CefMainRunner::ContentMainRun(bool* initialized,
|
||||||
|
|
||||||
// We need to wait until content::ContentMainRun has finished.
|
// We need to wait until content::ContentMainRun has finished.
|
||||||
uithread_startup_event.Wait();
|
uithread_startup_event.Wait();
|
||||||
|
|
||||||
|
if (exit_code != content::RESULT_CODE_NORMAL_EXIT) {
|
||||||
|
// content::ContentMainRun was not successful (for example, due to process
|
||||||
|
// singleton relaunch). Stop the UI thread and block until done.
|
||||||
|
ui_thread_->Stop();
|
||||||
|
ui_thread_.reset();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
*initialized = true;
|
*initialized = true;
|
||||||
main_delegate_->BeforeUIThreadInitialize();
|
main_delegate_->BeforeUIThreadInitialize();
|
||||||
|
|
|
@ -58,6 +58,11 @@ void ChromeMainRunnerDelegate::BeforeMainThreadRun(
|
||||||
|
|
||||||
void ChromeMainRunnerDelegate::BeforeMainMessageLoopRun(
|
void ChromeMainRunnerDelegate::BeforeMainMessageLoopRun(
|
||||||
base::RunLoop* run_loop) {
|
base::RunLoop* run_loop) {
|
||||||
|
// May be nullptr if content::ContentMainRun exits early.
|
||||||
|
if (!g_browser_process) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// The ScopedKeepAlive instance triggers shutdown logic when released on the
|
// The ScopedKeepAlive instance triggers shutdown logic when released on the
|
||||||
// UI thread before terminating the message loop (e.g. from CefQuitMessageLoop
|
// UI thread before terminating the message loop (e.g. from CefQuitMessageLoop
|
||||||
// or FinishShutdownOnUIThread when running with multi-threaded message loop).
|
// or FinishShutdownOnUIThread when running with multi-threaded message loop).
|
||||||
|
@ -67,12 +72,17 @@ void ChromeMainRunnerDelegate::BeforeMainMessageLoopRun(
|
||||||
// The QuitClosure will be executed from BrowserProcessImpl::Unpin() via
|
// The QuitClosure will be executed from BrowserProcessImpl::Unpin() via
|
||||||
// KeepAliveRegistry when the last ScopedKeepAlive is released.
|
// KeepAliveRegistry when the last ScopedKeepAlive is released.
|
||||||
// ScopedKeepAlives are also held by Browser objects.
|
// ScopedKeepAlives are also held by Browser objects.
|
||||||
DCHECK(g_browser_process);
|
|
||||||
static_cast<BrowserProcessImpl*>(g_browser_process)
|
static_cast<BrowserProcessImpl*>(g_browser_process)
|
||||||
->SetQuitClosure(run_loop->QuitClosure());
|
->SetQuitClosure(run_loop->QuitClosure());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChromeMainRunnerDelegate::HandleMainMessageLoopQuit() {
|
bool ChromeMainRunnerDelegate::HandleMainMessageLoopQuit() {
|
||||||
|
// May be nullptr if content::ContentMainRun exits early.
|
||||||
|
if (!g_browser_process) {
|
||||||
|
// Proceed with direct execution of the QuitClosure().
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// May be called multiple times. See comments in RunMainMessageLoopBefore.
|
// May be called multiple times. See comments in RunMainMessageLoopBefore.
|
||||||
keep_alive_.reset();
|
keep_alive_.reset();
|
||||||
|
|
||||||
|
|
|
@ -58,8 +58,20 @@ void RootWindowViews::Init(RootWindow::Delegate* delegate,
|
||||||
CreateClientHandler(config_->url);
|
CreateClientHandler(config_->url);
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
|
|
||||||
|
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||||
|
// Execute GetRequestContext() on the main thread.
|
||||||
|
MAIN_POST_CLOSURE(base::BindOnce(
|
||||||
|
[](scoped_refptr<RootWindowViews> self,
|
||||||
|
const CefBrowserSettings& settings) {
|
||||||
|
// Continue initialization on the UI thread.
|
||||||
|
self->InitOnUIThread(settings,
|
||||||
|
self->delegate_->GetRequestContext(self.get()));
|
||||||
|
},
|
||||||
|
scoped_refptr<RootWindowViews>(this), settings));
|
||||||
|
} else {
|
||||||
// Continue initialization on the UI thread.
|
// Continue initialization on the UI thread.
|
||||||
InitOnUIThread(settings, delegate_->GetRequestContext(this));
|
InitOnUIThread(settings, delegate_->GetRequestContext(this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RootWindowViews::InitAsPopup(RootWindow::Delegate* delegate,
|
void RootWindowViews::InitAsPopup(RootWindow::Delegate* delegate,
|
||||||
|
|
Loading…
Reference in New Issue