| Index: remoting/client/plugin/chromoting_instance.cc
|
| diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc
|
| index 808dd8473caa4e9c1b1621da145f39c51f66c2d8..8435e1e59517df04d18d0aa810815cc410ab8c4b 100644
|
| --- a/remoting/client/plugin/chromoting_instance.cc
|
| +++ b/remoting/client/plugin/chromoting_instance.cc
|
| @@ -91,18 +91,20 @@ std::string ConnectionErrorToString(ChromotingInstance::ConnectionError error) {
|
| return "";
|
| }
|
|
|
| -} // namespace
|
| -
|
| // This flag blocks LOGs to the UI if we're already in the middle of logging
|
| // to the UI. This prevents a potential infinite loop if we encounter an error
|
| // while sending the log message to the UI.
|
| -static bool g_logging_to_plugin = false;
|
| -static bool g_has_logging_instance = false;
|
| -static ChromotingInstance* g_logging_instance = NULL;
|
| -static logging::LogMessageHandlerFunction g_logging_old_handler = NULL;
|
| -
|
| -static base::LazyInstance<base::Lock>::Leaky
|
| +bool g_logging_to_plugin = false;
|
| +bool g_has_logging_instance = false;
|
| +base::LazyInstance<scoped_refptr<base::SingleThreadTaskRunner> >::Leaky
|
| + g_logging_task_runner = LAZY_INSTANCE_INITIALIZER;
|
| +base::LazyInstance<base::WeakPtr<ChromotingInstance> >::Leaky
|
| + g_logging_instance = LAZY_INSTANCE_INITIALIZER;
|
| +base::LazyInstance<base::Lock>::Leaky
|
| g_logging_lock = LAZY_INSTANCE_INITIALIZER;
|
| +logging::LogMessageHandlerFunction g_logging_old_handler = NULL;
|
| +
|
| +} // namespace
|
|
|
| // String sent in the "hello" message to the plugin to describe features.
|
| const char ChromotingInstance::kApiFeatures[] =
|
| @@ -134,7 +136,7 @@ ChromotingInstance::ChromotingInstance(PP_Instance pp_instance)
|
| plugin_message_loop_(
|
| new PluginMessageLoopProxy(&plugin_thread_delegate_)),
|
| context_(plugin_message_loop_),
|
| - thread_proxy_(new ScopedThreadProxy(plugin_message_loop_)) {
|
| + weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
|
| RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL);
|
| RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
|
|
|
| @@ -152,10 +154,6 @@ ChromotingInstance::ChromotingInstance(PP_Instance pp_instance)
|
| ChromotingInstance::~ChromotingInstance() {
|
| DCHECK(plugin_message_loop_->BelongsToCurrentThread());
|
|
|
| - // Detach the log proxy so we don't log anything else to the UI.
|
| - // This needs to be done before the instance is unregistered for logging.
|
| - thread_proxy_->Detach();
|
| -
|
| // Unregister this instance so that debug log messages will no longer be sent
|
| // to it. This will stop all logging in all Chromoting instances.
|
| UnregisterLoggingInstance();
|
| @@ -170,10 +168,7 @@ ChromotingInstance::~ChromotingInstance() {
|
| // Stopping the context shuts down all chromoting threads.
|
| context_.Stop();
|
|
|
| - // Delete |thread_proxy_| before we detach |plugin_message_loop_|,
|
| - // otherwise ScopedThreadProxy may DCHECK when being destroyed.
|
| - thread_proxy_.reset();
|
| -
|
| + // Ensure that nothing touches the plugin thread delegate after this point.
|
| plugin_message_loop_->Detach();
|
| }
|
|
|
| @@ -625,7 +620,8 @@ void ChromotingInstance::RegisterLoggingInstance() {
|
| // and display them to the user.
|
| // If multiple plugins are run, then the last one registered will handle all
|
| // logging for all instances.
|
| - g_logging_instance = this;
|
| + g_logging_instance.Get() = weak_factory_.GetWeakPtr();
|
| + g_logging_task_runner.Get() = plugin_message_loop_;
|
| g_has_logging_instance = true;
|
| }
|
|
|
| @@ -633,12 +629,13 @@ void ChromotingInstance::UnregisterLoggingInstance() {
|
| base::AutoLock lock(g_logging_lock.Get());
|
|
|
| // Don't unregister unless we're the currently registered instance.
|
| - if (this != g_logging_instance)
|
| + if (this != g_logging_instance.Get().get())
|
| return;
|
|
|
| // Unregister this instance for logging.
|
| g_has_logging_instance = false;
|
| - g_logging_instance = NULL;
|
| + g_logging_instance.Get().reset();
|
| + g_logging_task_runner.Get() = NULL;
|
|
|
| VLOG(1) << "Unregistering global log handler";
|
| }
|
| @@ -660,24 +657,28 @@ bool ChromotingInstance::LogToUI(int severity, const char* file, int line,
|
| // the lock and check |g_logging_instance| unnecessarily. This is not
|
| // problematic because we always set |g_logging_instance| inside a lock.
|
| if (g_has_logging_instance) {
|
| - // Do not LOG anything while holding this lock or else the code will
|
| - // deadlock while trying to re-get the lock we're already in.
|
| - base::AutoLock lock(g_logging_lock.Get());
|
| - if (g_logging_instance &&
|
| - // If |g_logging_to_plugin| is set and we're on the logging thread, then
|
| - // this LOG message came from handling a previous LOG message and we
|
| - // should skip it to avoid an infinite loop of LOG messages.
|
| - // We don't have a lock around |g_in_processtoui|, but that's OK since
|
| - // the value is only read/written on the logging thread.
|
| - (!g_logging_instance->plugin_message_loop_->BelongsToCurrentThread() ||
|
| - !g_logging_to_plugin)) {
|
| + scoped_refptr<base::SingleThreadTaskRunner> logging_task_runner;
|
| + base::WeakPtr<ChromotingInstance> logging_instance;
|
| +
|
| + {
|
| + base::AutoLock lock(g_logging_lock.Get());
|
| + // If we're on the logging thread and |g_logging_to_plugin| is set then
|
| + // this LOG message came from handling a previous LOG message and we
|
| + // should skip it to avoid an infinite loop of LOG messages.
|
| + if (!g_logging_task_runner.Get()->BelongsToCurrentThread() ||
|
| + !g_logging_to_plugin) {
|
| + logging_task_runner = g_logging_task_runner.Get();
|
| + logging_instance = g_logging_instance.Get();
|
| + }
|
| + }
|
| +
|
| + if (logging_task_runner.get()) {
|
| std::string message = remoting::GetTimestampString();
|
| message += (str.c_str() + message_start);
|
| - // |thread_proxy_| is safe to use here because we detach it before
|
| - // tearing down the |g_logging_instance|.
|
| - g_logging_instance->thread_proxy_->PostTask(
|
| +
|
| + logging_task_runner->PostTask(
|
| FROM_HERE, base::Bind(&ChromotingInstance::ProcessLogToUI,
|
| - base::Unretained(g_logging_instance), message));
|
| + logging_instance, message));
|
| }
|
| }
|
|
|
| @@ -692,6 +693,7 @@ void ChromotingInstance::ProcessLogToUI(const std::string& message) {
|
| // This flag (which is set only here) is used to prevent LogToUI from posting
|
| // new tasks while we're in the middle of servicing a LOG call. This can
|
| // happen if the call to LogDebugInfo tries to LOG anything.
|
| + // Since it is read on the plugin thread, we don't need to lock to set it.
|
| g_logging_to_plugin = true;
|
| scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue());
|
| data->SetString("message", message);
|
|
|