mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-18 05:00:48 +01:00
Merge revision 1078 changes:
- When running in single-process mode wait for the render thread to stop before shutting down the context (issue #570). git-svn-id: https://chromiumembedded.googlecode.com/svn/branches/1364@1079 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
545dc47102
commit
ce81e551d6
@ -13,6 +13,7 @@
|
|||||||
#include "libcef/browser/thread_util.h"
|
#include "libcef/browser/thread_util.h"
|
||||||
#include "libcef/browser/trace_subscriber.h"
|
#include "libcef/browser/trace_subscriber.h"
|
||||||
#include "libcef/common/main_delegate.h"
|
#include "libcef/common/main_delegate.h"
|
||||||
|
#include "libcef/renderer/content_renderer_client.h"
|
||||||
|
|
||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
@ -20,6 +21,7 @@
|
|||||||
#include "base/synchronization/waitable_event.h"
|
#include "base/synchronization/waitable_event.h"
|
||||||
#include "content/public/app/content_main.h"
|
#include "content/public/app/content_main.h"
|
||||||
#include "content/public/app/content_main_runner.h"
|
#include "content/public/app/content_main_runner.h"
|
||||||
|
#include "content/public/browser/render_process_host.h"
|
||||||
#include "content/public/common/content_switches.h"
|
#include "content/public/common/content_switches.h"
|
||||||
#include "ui/base/ui_base_switches.h"
|
#include "ui/base/ui_base_switches.h"
|
||||||
|
|
||||||
@ -341,6 +343,11 @@ void CefContext::FinishShutdownOnUIThread(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CefContext::FinalizeShutdown() {
|
void CefContext::FinalizeShutdown() {
|
||||||
|
if (content::RenderProcessHost::run_renderer_in_process()) {
|
||||||
|
// Blocks until RenderProcess cleanup is complete.
|
||||||
|
CefContentRendererClient::Get()->RunSingleProcessCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
// Shut down the browser runner or UI thread.
|
// Shut down the browser runner or UI thread.
|
||||||
main_delegate_->ShutdownBrowser();
|
main_delegate_->ShutdownBrowser();
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ MSVC_POP_WARNING();
|
|||||||
|
|
||||||
#include "libcef/renderer/content_renderer_client.h"
|
#include "libcef/renderer/content_renderer_client.h"
|
||||||
|
|
||||||
|
#include "libcef/browser/context.h"
|
||||||
#include "libcef/common/cef_messages.h"
|
#include "libcef/common/cef_messages.h"
|
||||||
#include "libcef/common/cef_switches.h"
|
#include "libcef/common/cef_switches.h"
|
||||||
#include "libcef/common/content_client.h"
|
#include "libcef/common/content_client.h"
|
||||||
@ -30,6 +31,8 @@ MSVC_POP_WARNING();
|
|||||||
#include "base/path_service.h"
|
#include "base/path_service.h"
|
||||||
#include "base/string_number_conversions.h"
|
#include "base/string_number_conversions.h"
|
||||||
#include "content/common/child_thread.h"
|
#include "content/common/child_thread.h"
|
||||||
|
#include "content/public/browser/browser_thread.h"
|
||||||
|
#include "content/public/browser/render_process_host.h"
|
||||||
#include "content/public/renderer/render_thread.h"
|
#include "content/public/renderer/render_thread.h"
|
||||||
#include "content/public/renderer/render_view.h"
|
#include "content/public/renderer/render_view.h"
|
||||||
#include "ipc/ipc_sync_channel.h"
|
#include "ipc/ipc_sync_channel.h"
|
||||||
@ -208,7 +211,8 @@ struct CefContentRendererClient::SchemeInfo {
|
|||||||
|
|
||||||
CefContentRendererClient::CefContentRendererClient()
|
CefContentRendererClient::CefContentRendererClient()
|
||||||
: devtools_agent_count_(0),
|
: devtools_agent_count_(0),
|
||||||
uncaught_exception_stack_size_(0) {
|
uncaught_exception_stack_size_(0),
|
||||||
|
single_process_cleanup_complete_(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CefContentRendererClient::~CefContentRendererClient() {
|
CefContentRendererClient::~CefContentRendererClient() {
|
||||||
@ -411,6 +415,35 @@ void CefContentRendererClient::RemoveWorkerTaskRunner(int worker_id) {
|
|||||||
worker_task_runner_map_.erase(it);
|
worker_task_runner_map_.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CefContentRendererClient::RunSingleProcessCleanup() {
|
||||||
|
DCHECK(content::RenderProcessHost::run_renderer_in_process());
|
||||||
|
|
||||||
|
// Make sure the render thread was actually started.
|
||||||
|
if (!render_task_runner_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
|
||||||
|
RunSingleProcessCleanupOnUIThread();
|
||||||
|
} else {
|
||||||
|
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
|
||||||
|
base::Bind(&CefContentRendererClient::RunSingleProcessCleanupOnUIThread,
|
||||||
|
base::Unretained(this)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the render thread cleanup to complete. Spin instead of using
|
||||||
|
// base::WaitableEvent because calling Wait() is not allowed on the UI
|
||||||
|
// thread.
|
||||||
|
bool complete = false;
|
||||||
|
do {
|
||||||
|
{
|
||||||
|
base::AutoLock lock_scope(single_process_cleanup_lock_);
|
||||||
|
complete = single_process_cleanup_complete_;
|
||||||
|
}
|
||||||
|
if (!complete)
|
||||||
|
base::PlatformThread::YieldCurrentThread();
|
||||||
|
} while (!complete);
|
||||||
|
}
|
||||||
|
|
||||||
void CefContentRendererClient::RenderThreadStarted() {
|
void CefContentRendererClient::RenderThreadStarted() {
|
||||||
render_task_runner_ = base::MessageLoopProxy::current();
|
render_task_runner_ = base::MessageLoopProxy::current();
|
||||||
observer_.reset(new CefRenderProcessObserver());
|
observer_.reset(new CefRenderProcessObserver());
|
||||||
@ -419,6 +452,12 @@ void CefContentRendererClient::RenderThreadStarted() {
|
|||||||
thread->AddObserver(observer_.get());
|
thread->AddObserver(observer_.get());
|
||||||
thread->GetChannel()->AddFilter(new CefRenderMessageFilter);
|
thread->GetChannel()->AddFilter(new CefRenderMessageFilter);
|
||||||
|
|
||||||
|
if (content::RenderProcessHost::run_renderer_in_process()) {
|
||||||
|
// When running in single-process mode register as a destruction observer
|
||||||
|
// on the render thread's MessageLoop.
|
||||||
|
MessageLoop::current()->AddDestructionObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
// Note that under Linux, the media library will normally already have
|
// Note that under Linux, the media library will normally already have
|
||||||
// been initialized by the Zygote before this instance became a Renderer.
|
// been initialized by the Zygote before this instance became a Renderer.
|
||||||
FilePath media_path;
|
FilePath media_path;
|
||||||
@ -592,3 +631,37 @@ void CefContentRendererClient::WillReleaseScriptContext(
|
|||||||
|
|
||||||
CefV8ReleaseContext(context);
|
CefV8ReleaseContext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CefContentRendererClient::WillDestroyCurrentMessageLoop() {
|
||||||
|
base::AutoLock lock_scope(single_process_cleanup_lock_);
|
||||||
|
single_process_cleanup_complete_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefContentRendererClient::RunSingleProcessCleanupOnUIThread() {
|
||||||
|
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
||||||
|
|
||||||
|
// Clean up the single existing RenderProcessHost.
|
||||||
|
content::RenderProcessHost* host = NULL;
|
||||||
|
content::RenderProcessHost::iterator iterator(
|
||||||
|
content::RenderProcessHost::AllHostsIterator());
|
||||||
|
if (!iterator.IsAtEnd()) {
|
||||||
|
host = iterator.GetCurrentValue();
|
||||||
|
host->Cleanup();
|
||||||
|
iterator.Advance();
|
||||||
|
DCHECK(iterator.IsAtEnd());
|
||||||
|
}
|
||||||
|
DCHECK(host);
|
||||||
|
|
||||||
|
// Clear the run_renderer_in_process() flag to avoid a DCHECK in the
|
||||||
|
// RenderProcessHost destructor.
|
||||||
|
content::RenderProcessHost::SetRunRendererInProcess(false);
|
||||||
|
|
||||||
|
// Deletion of the RenderProcessHost object will stop the render thread and
|
||||||
|
// result in a call to WillDestroyCurrentMessageLoop.
|
||||||
|
// Cleanup() will cause deletion to be posted as a task on the UI thread but
|
||||||
|
// this task will only execute when running in multi-threaded message loop
|
||||||
|
// mode (because otherwise the UI message loop has already stopped). Therefore
|
||||||
|
// we need to explicitly delete the object when not running in this mode.
|
||||||
|
if (!_Context->settings().multi_threaded_message_loop)
|
||||||
|
delete host;
|
||||||
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "base/compiler_specific.h"
|
#include "base/compiler_specific.h"
|
||||||
#include "base/memory/scoped_ptr.h"
|
#include "base/memory/scoped_ptr.h"
|
||||||
|
#include "base/message_loop.h"
|
||||||
#include "base/sequenced_task_runner.h"
|
#include "base/sequenced_task_runner.h"
|
||||||
#include "content/public/renderer/content_renderer_client.h"
|
#include "content/public/renderer/content_renderer_client.h"
|
||||||
|
|
||||||
@ -23,7 +24,8 @@ class CefRenderProcessObserver;
|
|||||||
class CefWebWorkerScriptObserver;
|
class CefWebWorkerScriptObserver;
|
||||||
struct Cef_CrossOriginWhiteListEntry_Params;
|
struct Cef_CrossOriginWhiteListEntry_Params;
|
||||||
|
|
||||||
class CefContentRendererClient : public content::ContentRendererClient {
|
class CefContentRendererClient : public content::ContentRendererClient,
|
||||||
|
public MessageLoop::DestructionObserver {
|
||||||
public:
|
public:
|
||||||
CefContentRendererClient();
|
CefContentRendererClient();
|
||||||
virtual ~CefContentRendererClient();
|
virtual ~CefContentRendererClient();
|
||||||
@ -72,6 +74,10 @@ class CefContentRendererClient : public content::ContentRendererClient {
|
|||||||
// Remove the task runner associated with the specified worker ID.
|
// Remove the task runner associated with the specified worker ID.
|
||||||
void RemoveWorkerTaskRunner(int worker_id);
|
void RemoveWorkerTaskRunner(int worker_id);
|
||||||
|
|
||||||
|
// Perform cleanup work that needs to occur before shutdown when running in
|
||||||
|
// single-process mode. Blocks until cleanup is complete.
|
||||||
|
void RunSingleProcessCleanup();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ContentRendererClient implementation.
|
// ContentRendererClient implementation.
|
||||||
virtual void RenderThreadStarted() OVERRIDE;
|
virtual void RenderThreadStarted() OVERRIDE;
|
||||||
@ -89,6 +95,12 @@ class CefContentRendererClient : public content::ContentRendererClient {
|
|||||||
v8::Handle<v8::Context> context,
|
v8::Handle<v8::Context> context,
|
||||||
int world_id) OVERRIDE;
|
int world_id) OVERRIDE;
|
||||||
|
|
||||||
|
// MessageLoop::DestructionObserver implementation.
|
||||||
|
virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
|
||||||
|
|
||||||
|
// Perform cleanup work for single-process mode.
|
||||||
|
void RunSingleProcessCleanupOnUIThread();
|
||||||
|
|
||||||
scoped_refptr<base::SequencedTaskRunner> render_task_runner_;
|
scoped_refptr<base::SequencedTaskRunner> render_task_runner_;
|
||||||
scoped_ptr<CefRenderProcessObserver> observer_;
|
scoped_ptr<CefRenderProcessObserver> observer_;
|
||||||
scoped_ptr<CefWebWorkerScriptObserver> worker_script_observer_;
|
scoped_ptr<CefWebWorkerScriptObserver> worker_script_observer_;
|
||||||
@ -115,6 +127,11 @@ class CefContentRendererClient : public content::ContentRendererClient {
|
|||||||
WorkerTaskRunnerMap;
|
WorkerTaskRunnerMap;
|
||||||
WorkerTaskRunnerMap worker_task_runner_map_;
|
WorkerTaskRunnerMap worker_task_runner_map_;
|
||||||
base::Lock worker_task_runner_lock_;
|
base::Lock worker_task_runner_lock_;
|
||||||
|
|
||||||
|
// Used in single-process mode to test when cleanup is complete.
|
||||||
|
// Access must be protected by |single_process_cleanup_lock_|.
|
||||||
|
bool single_process_cleanup_complete_;
|
||||||
|
base::Lock single_process_cleanup_lock_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_RENDERER_CONTENT_RENDERER_CLIENT_H_
|
#endif // CEF_LIBCEF_RENDERER_CONTENT_RENDERER_CLIENT_H_
|
||||||
|
Loading…
x
Reference in New Issue
Block a user