summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/synchronization/condition_variable_posix.cc3
-rw-r--r--base/synchronization/condition_variable_win.cc3
-rw-r--r--base/synchronization/waitable_event_posix.cc6
-rw-r--r--base/synchronization/waitable_event_win.cc4
-rw-r--r--base/test/thread_test_helper.cc2
-rw-r--r--base/threading/sequenced_worker_pool.cc2
-rw-r--r--base/threading/simple_thread.cc7
-rw-r--r--base/threading/simple_thread.h2
-rw-r--r--base/threading/thread.cc2
-rw-r--r--base/threading/thread_restrictions.cc23
-rw-r--r--base/threading/thread_restrictions.h77
-rw-r--r--chrome/browser/automation/testing_automation_provider.cc1
-rw-r--r--chrome/browser/io_thread.cc5
-rw-r--r--chrome/browser/metrics/metrics_service.cc5
-rw-r--r--chrome/browser/net/predictor.cc6
-rw-r--r--content/browser/browser_main_loop.cc1
-rw-r--r--content/browser/browser_process_sub_thread.cc9
-rw-r--r--content/browser/renderer_host/render_widget_helper.cc6
-rw-r--r--content/browser/renderer_host/text_input_client_mac.mm7
-rw-r--r--media/audio/audio_output_controller.cc3
-rw-r--r--net/base/file_stream_posix.cc1
-rw-r--r--net/base/file_stream_win.cc1
-rw-r--r--net/base/network_change_notifier_linux.cc51
-rw-r--r--net/disk_cache/backend_impl.cc2
-rw-r--r--net/disk_cache/in_flight_io.cc7
25 files changed, 199 insertions, 37 deletions
diff --git a/base/synchronization/condition_variable_posix.cc b/base/synchronization/condition_variable_posix.cc
index fc68b64..25edf16 100644
--- a/base/synchronization/condition_variable_posix.cc
+++ b/base/synchronization/condition_variable_posix.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/synchronization/lock.h"
+#include "base/threading/thread_restrictions.h"
#include "base/time.h"
namespace base {
@@ -29,6 +30,7 @@ ConditionVariable::~ConditionVariable() {
}
void ConditionVariable::Wait() {
+ base::ThreadRestrictions::AssertWaitAllowed();
#if !defined(NDEBUG)
user_lock_->CheckHeldAndUnmark();
#endif
@@ -40,6 +42,7 @@ void ConditionVariable::Wait() {
}
void ConditionVariable::TimedWait(const TimeDelta& max_time) {
+ base::ThreadRestrictions::AssertWaitAllowed();
int64 usecs = max_time.InMicroseconds();
// The timeout argument to pthread_cond_timedwait is in absolute time.
diff --git a/base/synchronization/condition_variable_win.cc b/base/synchronization/condition_variable_win.cc
index 4f6827f..f32778f 100644
--- a/base/synchronization/condition_variable_win.cc
+++ b/base/synchronization/condition_variable_win.cc
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/synchronization/lock.h"
+#include "base/threading/thread_restrictions.h"
#include "base/time.h"
namespace {
@@ -94,6 +95,7 @@ void WinVistaCondVar::Wait() {
}
void WinVistaCondVar::TimedWait(const TimeDelta& max_time) {
+ base::ThreadRestrictions::AssertWaitAllowed();
DWORD timeout = static_cast<DWORD>(max_time.InMilliseconds());
CRITICAL_SECTION* cs = user_lock_.lock_.os_lock();
@@ -240,6 +242,7 @@ void WinXPCondVar::Wait() {
}
void WinXPCondVar::TimedWait(const TimeDelta& max_time) {
+ base::ThreadRestrictions::AssertWaitAllowed();
Event* waiting_event;
HANDLE handle;
{
diff --git a/base/synchronization/waitable_event_posix.cc b/base/synchronization/waitable_event_posix.cc
index fbf8d10..714c111 100644
--- a/base/synchronization/waitable_event_posix.cc
+++ b/base/synchronization/waitable_event_posix.cc
@@ -5,11 +5,11 @@
#include <algorithm>
#include <vector>
+#include "base/logging.h"
#include "base/synchronization/waitable_event.h"
-
#include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.h"
-#include "base/logging.h"
+#include "base/threading/thread_restrictions.h"
// -----------------------------------------------------------------------------
// A WaitableEvent on POSIX is implemented as a wait-list. Currently we don't
@@ -158,6 +158,7 @@ void WaitableEvent::Wait() {
}
bool WaitableEvent::TimedWait(const TimeDelta& max_time) {
+ base::ThreadRestrictions::AssertWaitAllowed();
const Time end_time(Time::Now() + max_time);
const bool finite_time = max_time.ToInternalValue() >= 0;
@@ -224,6 +225,7 @@ cmp_fst_addr(const std::pair<WaitableEvent*, unsigned> &a,
// static
size_t WaitableEvent::WaitMany(WaitableEvent** raw_waitables,
size_t count) {
+ base::ThreadRestrictions::AssertWaitAllowed();
DCHECK(count) << "Cannot wait on no events";
// We need to acquire the locks in a globally consistent order. Thus we sort
diff --git a/base/synchronization/waitable_event_win.cc b/base/synchronization/waitable_event_win.cc
index 31932bd..28f8fc3 100644
--- a/base/synchronization/waitable_event_win.cc
+++ b/base/synchronization/waitable_event_win.cc
@@ -8,6 +8,7 @@
#include <windows.h>
#include "base/logging.h"
+#include "base/threading/thread_restrictions.h"
#include "base/time.h"
namespace base {
@@ -47,6 +48,7 @@ bool WaitableEvent::IsSignaled() {
}
void WaitableEvent::Wait() {
+ base::ThreadRestrictions::AssertWaitAllowed();
DWORD result = WaitForSingleObject(handle_, INFINITE);
// It is most unexpected that this should ever fail. Help consumers learn
// about it if it should ever fail.
@@ -54,6 +56,7 @@ void WaitableEvent::Wait() {
}
bool WaitableEvent::TimedWait(const TimeDelta& max_time) {
+ base::ThreadRestrictions::AssertWaitAllowed();
DCHECK(max_time >= TimeDelta::FromMicroseconds(0));
// Be careful here. TimeDelta has a precision of microseconds, but this API
// is in milliseconds. If there are 5.5ms left, should the delay be 5 or 6?
@@ -74,6 +77,7 @@ bool WaitableEvent::TimedWait(const TimeDelta& max_time) {
// static
size_t WaitableEvent::WaitMany(WaitableEvent** events, size_t count) {
+ base::ThreadRestrictions::AssertWaitAllowed();
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
CHECK_LE(count, MAXIMUM_WAIT_OBJECTS)
<< "Can only wait on " << MAXIMUM_WAIT_OBJECTS << " with WaitMany";
diff --git a/base/test/thread_test_helper.cc b/base/test/thread_test_helper.cc
index ad240b3..a91517d 100644
--- a/base/test/thread_test_helper.cc
+++ b/base/test/thread_test_helper.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/location.h"
+#include "base/threading/thread_restrictions.h"
namespace base {
@@ -20,6 +21,7 @@ bool ThreadTestHelper::Run() {
FROM_HERE, base::Bind(&ThreadTestHelper::RunInThread, this))) {
return false;
}
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
done_event_.Wait();
return test_result_;
}
diff --git a/base/threading/sequenced_worker_pool.cc b/base/threading/sequenced_worker_pool.cc
index 22f9152..59c4187 100644
--- a/base/threading/sequenced_worker_pool.cc
+++ b/base/threading/sequenced_worker_pool.cc
@@ -23,6 +23,7 @@
#include "base/synchronization/lock.h"
#include "base/threading/platform_thread.h"
#include "base/threading/simple_thread.h"
+#include "base/threading/thread_restrictions.h"
#include "base/time.h"
#include "base/tracked_objects.h"
@@ -625,6 +626,7 @@ void SequencedWorkerPool::Inner::Shutdown() {
TimeTicks shutdown_wait_begin = TimeTicks::Now();
{
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
AutoLock lock(lock_);
while (!CanShutdown())
can_shutdown_cv_.Wait();
diff --git a/base/threading/simple_thread.cc b/base/threading/simple_thread.cc
index a5dd763..5419c95 100644
--- a/base/threading/simple_thread.cc
+++ b/base/threading/simple_thread.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/threading/platform_thread.h"
+#include "base/threading/thread_restrictions.h"
#include "base/string_number_conversions.h"
namespace base {
@@ -30,6 +31,7 @@ void SimpleThread::Start() {
DCHECK(!HasBeenStarted()) << "Tried to Start a thread multiple times.";
bool success = PlatformThread::Create(options_.stack_size(), this, &thread_);
DCHECK(success);
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
event_.Wait(); // Wait for the thread to complete initialization.
}
@@ -40,6 +42,11 @@ void SimpleThread::Join() {
joined_ = true;
}
+bool SimpleThread::HasBeenStarted() {
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
+ return event_.IsSignaled();
+}
+
void SimpleThread::ThreadMain() {
tid_ = PlatformThread::CurrentId();
// Construct our full name of the form "name_prefix_/TID".
diff --git a/base/threading/simple_thread.h b/base/threading/simple_thread.h
index c864d46..47d063a 100644
--- a/base/threading/simple_thread.h
+++ b/base/threading/simple_thread.h
@@ -97,7 +97,7 @@ class BASE_EXPORT SimpleThread : public PlatformThread::Delegate {
PlatformThreadId tid() { return tid_; }
// Return True if Start() has ever been called.
- bool HasBeenStarted() { return event_.IsSignaled(); }
+ bool HasBeenStarted();
// Return True if Join() has evern been called.
bool HasBeenJoined() { return joined_; }
diff --git a/base/threading/thread.cc b/base/threading/thread.cc
index 7188e9f..d6913a7 100644
--- a/base/threading/thread.cc
+++ b/base/threading/thread.cc
@@ -8,6 +8,7 @@
#include "base/lazy_instance.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "base/threading/thread_local.h"
+#include "base/threading/thread_restrictions.h"
#include "base/synchronization/waitable_event.h"
namespace base {
@@ -76,6 +77,7 @@ bool Thread::StartWithOptions(const Options& options) {
}
// Wait for the thread to start and initialize message_loop_
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
startup_data.event.Wait();
// set it to NULL so we don't keep a pointer to some object on the stack.
diff --git a/base/threading/thread_restrictions.cc b/base/threading/thread_restrictions.cc
index b093fb4..2300a78 100644
--- a/base/threading/thread_restrictions.cc
+++ b/base/threading/thread_restrictions.cc
@@ -21,6 +21,9 @@ LazyInstance<ThreadLocalBoolean>::Leaky
LazyInstance<ThreadLocalBoolean>::Leaky
g_singleton_disallowed = LAZY_INSTANCE_INITIALIZER;
+LazyInstance<ThreadLocalBoolean>::Leaky
+ g_wait_disallowed = LAZY_INSTANCE_INITIALIZER;
+
} // anonymous namespace
// static
@@ -42,6 +45,7 @@ void ThreadRestrictions::AssertIOAllowed() {
}
}
+// static
bool ThreadRestrictions::SetSingletonAllowed(bool allowed) {
bool previous_disallowed = g_singleton_disallowed.Get().Get();
g_singleton_disallowed.Get().Set(!allowed);
@@ -58,6 +62,25 @@ void ThreadRestrictions::AssertSingletonAllowed() {
}
}
+// static
+void ThreadRestrictions::DisallowWaiting() {
+ g_wait_disallowed.Get().Set(true);
+}
+
+// static
+void ThreadRestrictions::AssertWaitAllowed() {
+ if (g_wait_disallowed.Get().Get()) {
+ LOG(FATAL) << "Waiting is not allowed to be used on this thread to prevent"
+ << "jank and deadlock.";
+ }
+}
+
+bool ThreadRestrictions::SetWaitAllowed(bool allowed) {
+ bool previous_disallowed = g_wait_disallowed.Get().Get();
+ g_wait_disallowed.Get().Set(!allowed);
+ return !previous_disallowed;
+}
+
} // namespace base
#endif // NDEBUG
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h
index fc8ab4b..f638cb3 100644
--- a/base/threading/thread_restrictions.h
+++ b/base/threading/thread_restrictions.h
@@ -8,8 +8,33 @@
#include "base/base_export.h"
#include "base/basictypes.h"
+class MetricsService;
+class RenderWidgetHelper;
+class TestingAutomationProvider;
+class TextInputClientMac;
+namespace chrome_browser_net {
+class Predictor;
+}
+namespace disk_cache {
+class BackendImpl;
+class InFlightIO;
+}
+namespace media {
+class AudioOutputController;
+}
+namespace net {
+class FileStreamPosix;
+class FileStreamWin;
+class NetworkManagerApi;
+}
+
namespace base {
+class SequencedWorkerPool;
+class SimpleThread;
+class Thread;
+class ThreadTestHelper;
+
// Certain behavior is disallowed on certain threads. ThreadRestrictions helps
// enforce these rules. Examples of such rules:
//
@@ -83,6 +108,13 @@ class BASE_EXPORT ThreadRestrictions {
// Check whether the current thread is allowed to use singletons (Singleton /
// LazyInstance). DCHECKs if not.
static void AssertSingletonAllowed();
+
+ // Disable waiting on the current thread. Threads start out in the *allowed*
+ // state. Returns the previous value.
+ static void DisallowWaiting();
+
+ // Check whether the current thread is allowed to wait, and DCHECK if not.
+ static void AssertWaitAllowed();
#else
// In Release builds, inline the empty definitions of these functions so
// that they can be compiled out.
@@ -90,9 +122,54 @@ class BASE_EXPORT ThreadRestrictions {
static void AssertIOAllowed() {}
static bool SetSingletonAllowed(bool allowed) { return true; }
static void AssertSingletonAllowed() {}
+ static void DisallowWaiting() {}
+ static void AssertWaitAllowed() {}
#endif
private:
+ // DO NOT ADD ANY OTHER FRIEND STATEMENTS, talk to jam or brettw first.
+ // BEGIN ALLOWED USAGE.
+ friend class ::RenderWidgetHelper;
+ friend class ::TestingAutomationProvider;
+ friend class SequencedWorkerPool;
+ friend class SimpleThread;
+ friend class Thread;
+ friend class ThreadTestHelper;
+ // END ALLOWED USAGE.
+ // BEGIN USAGE THAT NEEDS TO BE FIXED.
+ friend class chrome_browser_net::Predictor; // http://crbug.com/78451
+ friend class disk_cache::BackendImpl; // http://crbug.com/74623
+ friend class disk_cache::InFlightIO; // http://crbug.com/74623
+ friend class media::AudioOutputController; // http://crbug.com/120973
+ friend class net::FileStreamPosix; // http://crbug.com/74623
+ friend class net::FileStreamWin; // http://crbug.com/74623
+ friend class net::NetworkManagerApi; // http://crbug.com/125097
+ friend class ::TextInputClientMac; // http://crbug.com/121917
+ friend class ::MetricsService; // http://crbug.com/124954
+ // END USAGE THAT NEEDS TO BE FIXED.
+
+#ifndef NDEBUG
+ static bool SetWaitAllowed(bool allowed);
+#else
+ static bool SetWaitAllowed(bool allowed) { return true; }
+#endif
+
+ // Constructing a ScopedAllowWait temporarily allows waiting on the current
+ // thread. Doing this is almost always incorrect, which is why we limit who
+ // can use this through friend. If you find yourself needing to use this, find
+ // another way. Talk to jam or brettw.
+ class BASE_EXPORT ScopedAllowWait {
+ public:
+ ScopedAllowWait() { previous_value_ = SetWaitAllowed(true); }
+ ~ScopedAllowWait() { SetWaitAllowed(previous_value_); }
+ private:
+ // Whether singleton use is allowed when the ScopedAllowWait was
+ // constructed.
+ bool previous_value_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedAllowWait);
+ };
+
DISALLOW_IMPLICIT_CONSTRUCTORS(ThreadRestrictions);
};
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc
index a7ecae8..87e1564 100644
--- a/chrome/browser/automation/testing_automation_provider.cc
+++ b/chrome/browser/automation/testing_automation_provider.cc
@@ -325,6 +325,7 @@ void TestingAutomationProvider::Observe(
bool TestingAutomationProvider::OnMessageReceived(
const IPC::Message& message) {
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
bool handled = true;
bool deserialize_success = true;
IPC_BEGIN_MESSAGE_MAP_EX(TestingAutomationProvider,
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index 941df16..73fbaa0 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -17,7 +17,6 @@
#include "base/string_split.h"
#include "base/string_util.h"
#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_event_router_forwarder.h"
@@ -374,10 +373,6 @@ net::URLRequestContextGetter* IOThread::system_url_request_context_getter() {
}
void IOThread::Init() {
- // Though this thread is called the "IO" thread, it actually just routes
- // messages around; it shouldn't be allowed to perform any blocking disk I/O.
- base::ThreadRestrictions::SetIOAllowed(false);
-
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
#if defined(USE_NSS)
diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc
index 89eb0c2..0b692aa 100644
--- a/chrome/browser/metrics/metrics_service.cc
+++ b/chrome/browser/metrics/metrics_service.cc
@@ -152,6 +152,7 @@
#include "base/string_number_conversions.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
+#include "base/threading/thread_restrictions.h"
#include "base/tracked_objects.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
@@ -810,7 +811,7 @@ void MetricsService::ReceivedProfilerData(
void MetricsService::FinishedReceivingProfilerData() {
DCHECK_EQ(INIT_TASK_SCHEDULED, state_);
- state_ = INIT_TASK_DONE;
+ state_ = INIT_TASK_DONE;
}
std::string MetricsService::GenerateClientID() {
@@ -1461,6 +1462,8 @@ void MetricsService::LogCleanShutdown() {
base::WaitableEvent done_writing(false, false);
BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
base::Bind(Signal, &done_writing));
+ // http://crbug.com/124954
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
done_writing.TimedWait(base::TimeDelta::FromHours(1));
// Redundant setting to assure that we always reset this value at shutdown
diff --git a/chrome/browser/net/predictor.cc b/chrome/browser/net/predictor.cc
index f91e51e..5df69b86 100644
--- a/chrome/browser/net/predictor.cc
+++ b/chrome/browser/net/predictor.cc
@@ -18,6 +18,7 @@
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread_restrictions.h"
#include "base/time.h"
#include "base/values.h"
#include "chrome/browser/io_thread.h"
@@ -768,8 +769,11 @@ void Predictor::SaveStateForNextStartupAndTrim(PrefService* prefs) {
// TODO(jar): Synchronous waiting for the IO thread is a potential source
// to deadlocks and should be investigated. See http://crbug.com/78451.
DCHECK(posted);
- if (posted)
+ if (posted) {
+ // http://crbug.com/124954
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
completion.Wait();
+ }
}
}
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 1aed2d2..a2405fa 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -427,6 +427,7 @@ void BrowserMainLoop::CreateThreads() {
// If the UI thread blocks, the whole UI is unresponsive.
// Do not allow disk IO from the UI thread.
base::ThreadRestrictions::SetIOAllowed(false);
+ base::ThreadRestrictions::DisallowWaiting();
// When running the GPU thread in-process, avoid optimistically starting it
// since creating the GPU thread races against creation of the one-and-only
diff --git a/content/browser/browser_process_sub_thread.cc b/content/browser/browser_process_sub_thread.cc
index fb80cae..c521af2 100644
--- a/content/browser/browser_process_sub_thread.cc
+++ b/content/browser/browser_process_sub_thread.cc
@@ -9,6 +9,7 @@
#endif
#include "base/debug/leak_tracker.h"
+#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "content/browser/browser_child_process_host_impl.h"
#include "content/browser/in_process_webkit/indexed_db_key_utility_client.h"
@@ -36,6 +37,14 @@ void BrowserProcessSubThread::Init() {
notification_service_ = new NotificationServiceImpl;
BrowserThreadImpl::Init();
+
+ if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ // Though this thread is called the "IO" thread, it actually just routes
+ // messages around; it shouldn't be allowed to perform any blocking disk
+ // I/O.
+ base::ThreadRestrictions::SetIOAllowed(false);
+ base::ThreadRestrictions::DisallowWaiting();
+ }
}
void BrowserProcessSubThread::CleanUp() {
diff --git a/content/browser/renderer_host/render_widget_helper.cc b/content/browser/renderer_host/render_widget_helper.cc
index 2290b4e..e516e6c 100644
--- a/content/browser/renderer_host/render_widget_helper.cc
+++ b/content/browser/renderer_host/render_widget_helper.cc
@@ -9,6 +9,7 @@
#include "base/eintr_wrapper.h"
#include "base/lazy_instance.h"
#include "base/threading/thread.h"
+#include "base/threading/thread_restrictions.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -145,8 +146,8 @@ void RenderWidgetHelper::SimulateSwapOutACK(
bool RenderWidgetHelper::WaitForBackingStoreMsg(
int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) {
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg) {
base::TimeTicks time_start = base::TimeTicks::Now();
for (;;) {
@@ -183,6 +184,7 @@ bool RenderWidgetHelper::WaitForBackingStoreMsg(
if (max_sleep_time <= base::TimeDelta::FromMilliseconds(0))
break;
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
event_.TimedWait(max_sleep_time);
}
diff --git a/content/browser/renderer_host/text_input_client_mac.mm b/content/browser/renderer_host/text_input_client_mac.mm
index 933511e..b026920e 100644
--- a/content/browser/renderer_host/text_input_client_mac.mm
+++ b/content/browser/renderer_host/text_input_client_mac.mm
@@ -6,6 +6,7 @@
#include "base/memory/singleton.h"
#include "base/metrics/histogram.h"
+#include "base/threading/thread_restrictions.h"
#include "base/time.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/text_input_client_messages.h"
@@ -41,6 +42,8 @@ NSUInteger TextInputClientMac::GetCharacterIndexAtPoint(RenderWidgetHost* rwh,
RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
rwhi->Send(new TextInputClientMsg_CharacterIndexForPoint(rwhi->GetRoutingID(),
point));
+ // http://crbug.com/121917
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
AfterRequest();
@@ -60,6 +63,8 @@ NSRect TextInputClientMac::GetFirstRectForRange(RenderWidgetHost* rwh,
rwhi->Send(
new TextInputClientMsg_FirstRectForCharacterRange(rwhi->GetRoutingID(),
ui::Range(range)));
+ // http://crbug.com/121917
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
AfterRequest();
@@ -79,6 +84,8 @@ NSAttributedString* TextInputClientMac::GetAttributedSubstringFromRange(
RenderWidgetHostImpl* rwhi = RenderWidgetHostImpl::From(rwh);
rwhi->Send(new TextInputClientMsg_StringForRange(rwhi->GetRoutingID(),
ui::Range(range)));
+ // http://crbug.com/121917
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
condition_.TimedWait(base::TimeDelta::FromMilliseconds(kWaitTimeout));
AfterRequest();
diff --git a/media/audio/audio_output_controller.cc b/media/audio/audio_output_controller.cc
index c136432..1f8d78f 100644
--- a/media/audio/audio_output_controller.cc
+++ b/media/audio/audio_output_controller.cc
@@ -9,6 +9,7 @@
#include "base/message_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
+#include "base/threading/thread_restrictions.h"
#include "base/time.h"
using base::Time;
@@ -42,6 +43,8 @@ AudioOutputController::~AudioOutputController() {
if (!message_loop_.get() || message_loop_->BelongsToCurrentThread()) {
DoStopCloseAndClearStream(NULL);
} else {
+ // http://crbug.com/120973
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
WaitableEvent completion(true /* manual reset */,
false /* initial state */);
message_loop_->PostTask(FROM_HERE,
diff --git a/net/base/file_stream_posix.cc b/net/base/file_stream_posix.cc
index 0fe801d..e76bf83 100644
--- a/net/base/file_stream_posix.cc
+++ b/net/base/file_stream_posix.cc
@@ -644,6 +644,7 @@ void FileStreamPosix::OnClosed(const CompletionCallback& callback) {
}
void FileStreamPosix::WaitForIOCompletion() {
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
if (on_io_complete_.get()) {
on_io_complete_->Wait();
on_io_complete_.reset();
diff --git a/net/base/file_stream_win.cc b/net/base/file_stream_win.cc
index 97b1975..9dad2c6 100644
--- a/net/base/file_stream_win.cc
+++ b/net/base/file_stream_win.cc
@@ -727,6 +727,7 @@ void FileStreamWin::ResetOnIOComplete() {
}
void FileStreamWin::WaitForIOCompletion() {
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
if (on_io_complete_.get()) {
on_io_complete_->Wait();
on_io_complete_.reset();
diff --git a/net/base/network_change_notifier_linux.cc b/net/base/network_change_notifier_linux.cc
index 4f75542..a4bc595 100644
--- a/net/base/network_change_notifier_linux.cc
+++ b/net/base/network_change_notifier_linux.cc
@@ -24,6 +24,7 @@
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
+#include "base/threading/thread_restrictions.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_proxy.h"
@@ -63,6 +64,30 @@ enum {
NM_STATE_CONNECTED_GLOBAL = 70
};
+class DNSWatchDelegate : public FilePathWatcher::Delegate {
+ public:
+ explicit DNSWatchDelegate(const base::Closure& callback)
+ : callback_(callback) {}
+ virtual ~DNSWatchDelegate() {}
+ // FilePathWatcher::Delegate interface
+ virtual void OnFilePathChanged(const FilePath& path) OVERRIDE;
+ virtual void OnFilePathError(const FilePath& path) OVERRIDE;
+ private:
+ base::Closure callback_;
+ DISALLOW_COPY_AND_ASSIGN(DNSWatchDelegate);
+};
+
+void DNSWatchDelegate::OnFilePathChanged(const FilePath& path) {
+ // Calls NetworkChangeNotifier::NotifyObserversOfDNSChange().
+ callback_.Run();
+}
+
+void DNSWatchDelegate::OnFilePathError(const FilePath& path) {
+ LOG(ERROR) << "DNSWatchDelegate::OnFilePathError for " << path.value();
+}
+
+} // namespace
+
// A wrapper around NetworkManager's D-Bus API.
class NetworkManagerApi {
public:
@@ -232,35 +257,13 @@ bool NetworkManagerApi::StateIsOffline(uint32 state) {
}
bool NetworkManagerApi::IsCurrentlyOffline() {
+ // http://crbug.com/125097
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
offline_state_initialized_.Wait();
base::AutoLock lock(is_offline_lock_);
return is_offline_;
}
-class DNSWatchDelegate : public FilePathWatcher::Delegate {
- public:
- explicit DNSWatchDelegate(const base::Closure& callback)
- : callback_(callback) {}
- virtual ~DNSWatchDelegate() {}
- // FilePathWatcher::Delegate interface
- virtual void OnFilePathChanged(const FilePath& path) OVERRIDE;
- virtual void OnFilePathError(const FilePath& path) OVERRIDE;
- private:
- base::Closure callback_;
- DISALLOW_COPY_AND_ASSIGN(DNSWatchDelegate);
-};
-
-void DNSWatchDelegate::OnFilePathChanged(const FilePath& path) {
- // Calls NetworkChangeNotifier::NotifyObserversOfDNSChange().
- callback_.Run();
-}
-
-void DNSWatchDelegate::OnFilePathError(const FilePath& path) {
- LOG(ERROR) << "DNSWatchDelegate::OnFilePathError for " << path.value();
-}
-
-} // namespace
-
class NetworkChangeNotifierLinux::Thread
: public base::Thread, public MessageLoopForIO::Watcher {
public:
diff --git a/net/disk_cache/backend_impl.cc b/net/disk_cache/backend_impl.cc
index eb26567..20fd40f 100644
--- a/net/disk_cache/backend_impl.cc
+++ b/net/disk_cache/backend_impl.cc
@@ -369,6 +369,8 @@ BackendImpl::~BackendImpl() {
} else {
background_queue_.background_thread()->PostTask(
FROM_HERE, base::Bind(&FinalCleanupCallback, base::Unretained(this)));
+ // http://crbug.com/74623
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
done_.Wait();
}
}
diff --git a/net/disk_cache/in_flight_io.cc b/net/disk_cache/in_flight_io.cc
index 86c2dcc..51ad986 100644
--- a/net/disk_cache/in_flight_io.cc
+++ b/net/disk_cache/in_flight_io.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/threading/thread_restrictions.h"
namespace disk_cache {
@@ -82,7 +83,11 @@ void InFlightIO::OnIOComplete(BackgroundIO* operation) {
// Runs on the primary thread.
void InFlightIO::InvokeCallback(BackgroundIO* operation, bool cancel_task) {
- operation->io_completed()->Wait();
+ {
+ // http://crbug.com/74623
+ base::ThreadRestrictions::ScopedAllowWait allow_wait;
+ operation->io_completed()->Wait();
+ }
running_ = true;
if (cancel_task)