diff options
author | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-23 05:19:20 +0000 |
---|---|---|
committer | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-23 05:19:20 +0000 |
commit | ba74b0d2f492a1a7a310af5e69fa7a0812ce6f52 (patch) | |
tree | eacff9788a950e58118148b5cae3f236840a49b0 | |
parent | 3c24a4682e05dc4496c0a9d898872ac39d142817 (diff) | |
download | chromium_src-ba74b0d2f492a1a7a310af5e69fa7a0812ce6f52.zip chromium_src-ba74b0d2f492a1a7a310af5e69fa7a0812ce6f52.tar.gz chromium_src-ba74b0d2f492a1a7a310af5e69fa7a0812ce6f52.tar.bz2 |
Thread IO safety: annotate file_util, and block IO thread from doing IO
- Mark functions in file_util_posix as requiring permission to perform
disk actions.
- Mark the IO thread as disallowed from performing disk actions.
- Temporarily work around the protections in places where we currently
have bugs.
BUG=59847,59849,60207,60211,60394
TEST=no dchecks in debug builds
Review URL: http://codereview.chromium.org/3872002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63636 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/file_util_posix.cc | 35 | ||||
-rw-r--r-- | base/shared_memory_posix.cc | 6 | ||||
-rw-r--r-- | base/sys_info_chromeos.cc | 7 | ||||
-rw-r--r-- | base/thread_restrictions.cc | 4 | ||||
-rw-r--r-- | base/thread_restrictions.h | 30 | ||||
-rw-r--r-- | chrome/browser/extensions/autoupdate_interceptor.cc | 8 | ||||
-rw-r--r-- | chrome/browser/io_thread.cc | 8 | ||||
-rw-r--r-- | chrome/browser/net/url_request_mock_http_job.cc | 5 | ||||
-rw-r--r-- | chrome/browser/net/url_request_mock_util.cc | 6 | ||||
-rw-r--r-- | chrome/browser/printing/print_dialog_cloud_uitest.cc | 9 | ||||
-rw-r--r-- | chrome/browser/service/service_process_control.cc | 10 | ||||
-rw-r--r-- | chrome/common/extensions/extension_resource.cc | 7 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 6 | ||||
-rw-r--r-- | net/url_request/url_request_file_job.cc | 10 |
14 files changed, 143 insertions, 8 deletions
diff --git a/base/file_util_posix.cc b/base/file_util_posix.cc index 8660054..119bc0e 100644 --- a/base/file_util_posix.cc +++ b/base/file_util_posix.cc @@ -39,6 +39,7 @@ #include "base/singleton.h" #include "base/string_util.h" #include "base/sys_string_conversions.h" +#include "base/thread_restrictions.h" #include "base/time.h" #include "base/utf_string_conversions.h" @@ -48,6 +49,7 @@ namespace { // Helper for NormalizeFilePath(), defined below. bool RealPath(const FilePath& path, FilePath* real_path) { + base::ThreadRestrictions::AssertIOAllowed(); // For realpath(). FilePath::CharType buf[PATH_MAX]; if (!realpath(path.value().c_str(), buf)) return false; @@ -63,11 +65,13 @@ bool RealPath(const FilePath& path, FilePath* real_path) { MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) typedef struct stat stat_wrapper_t; static int CallStat(const char *path, stat_wrapper_t *sb) { + base::ThreadRestrictions::AssertIOAllowed(); return stat(path, sb); } #else typedef struct stat64 stat_wrapper_t; static int CallStat(const char *path, stat_wrapper_t *sb) { + base::ThreadRestrictions::AssertIOAllowed(); return stat64(path, sb); } #endif @@ -80,6 +84,7 @@ static const char* kTempFileName = ".org.chromium.XXXXXX"; #endif bool AbsolutePath(FilePath* path) { + base::ThreadRestrictions::AssertIOAllowed(); // For realpath(). char full_path[PATH_MAX]; if (realpath(path->value().c_str(), full_path) == NULL) return false; @@ -89,6 +94,7 @@ bool AbsolutePath(FilePath* path) { int CountFilesCreatedAfter(const FilePath& path, const base::Time& comparison_time) { + base::ThreadRestrictions::AssertIOAllowed(); int file_count = 0; DIR* dir = opendir(path.value().c_str()); @@ -139,6 +145,7 @@ int CountFilesCreatedAfter(const FilePath& path, // that functionality. If not, remove from file_util_win.cc, otherwise add it // here. bool Delete(const FilePath& path, bool recursive) { + base::ThreadRestrictions::AssertIOAllowed(); const char* path_str = path.value().c_str(); stat_wrapper_t file_info; int test = CallStat(path_str, &file_info); @@ -178,6 +185,7 @@ bool Delete(const FilePath& path, bool recursive) { } bool Move(const FilePath& from_path, const FilePath& to_path) { + base::ThreadRestrictions::AssertIOAllowed(); // Windows compatibility: if to_path exists, from_path and to_path // must be the same type, either both files, or both directories. stat_wrapper_t to_file_info; @@ -202,12 +210,14 @@ bool Move(const FilePath& from_path, const FilePath& to_path) { } bool ReplaceFile(const FilePath& from_path, const FilePath& to_path) { + base::ThreadRestrictions::AssertIOAllowed(); return (rename(from_path.value().c_str(), to_path.value().c_str()) == 0); } bool CopyDirectory(const FilePath& from_path, const FilePath& to_path, bool recursive) { + base::ThreadRestrictions::AssertIOAllowed(); // Some old callers of CopyDirectory want it to support wildcards. // After some discussion, we decided to fix those callers. // Break loudly here if anyone tries to do this. @@ -307,14 +317,17 @@ bool CopyDirectory(const FilePath& from_path, } bool PathExists(const FilePath& path) { + base::ThreadRestrictions::AssertIOAllowed(); return access(path.value().c_str(), F_OK) == 0; } bool PathIsWritable(const FilePath& path) { + base::ThreadRestrictions::AssertIOAllowed(); return access(path.value().c_str(), W_OK) == 0; } bool DirectoryExists(const FilePath& path) { + base::ThreadRestrictions::AssertIOAllowed(); stat_wrapper_t file_info; if (CallStat(path.value().c_str(), &file_info) == 0) return S_ISDIR(file_info.st_mode); @@ -365,6 +378,7 @@ bool ReadFromFD(int fd, char* buffer, size_t bytes) { // file descriptor. |path| is set to the temporary file path. // This function does NOT unlink() the file. int CreateAndOpenFdForTemporaryFile(FilePath directory, FilePath* path) { + base::ThreadRestrictions::AssertIOAllowed(); // For call to mkstemp(). *path = directory.Append(kTempFileName); const std::string& tmpdir_string = path->value(); // this should be OK since mkstemp just replaces characters in place @@ -374,6 +388,7 @@ int CreateAndOpenFdForTemporaryFile(FilePath directory, FilePath* path) { } bool CreateTemporaryFile(FilePath* path) { + base::ThreadRestrictions::AssertIOAllowed(); // For call to close(). FilePath directory; if (!GetTempDir(&directory)) return false; @@ -401,6 +416,7 @@ FILE* CreateAndOpenTemporaryFileInDir(const FilePath& dir, FilePath* path) { } bool CreateTemporaryFileInDir(const FilePath& dir, FilePath* temp_file) { + base::ThreadRestrictions::AssertIOAllowed(); // For call to close(). int fd = CreateAndOpenFdForTemporaryFile(dir, temp_file); return ((fd >= 0) && !close(fd)); } @@ -408,6 +424,7 @@ bool CreateTemporaryFileInDir(const FilePath& dir, FilePath* temp_file) { static bool CreateTemporaryDirInDirImpl(const FilePath& base_dir, const FilePath::StringType& name_tmpl, FilePath* new_dir) { + base::ThreadRestrictions::AssertIOAllowed(); // For call to mkdtemp(). CHECK(name_tmpl.find("XXXXXX") != FilePath::StringType::npos) << "Directory name template must contain \"XXXXXX\"."; @@ -443,6 +460,7 @@ bool CreateNewTempDirectory(const FilePath::StringType& prefix, } bool CreateDirectory(const FilePath& full_path) { + base::ThreadRestrictions::AssertIOAllowed(); // For call to mkdir(). std::vector<FilePath> subpaths; // Collect a list of all parent directories. @@ -484,6 +502,7 @@ bool GetFileInfo(const FilePath& file_path, base::PlatformFileInfo* results) { } bool GetInode(const FilePath& path, ino_t* inode) { + base::ThreadRestrictions::AssertIOAllowed(); // For call to stat(). struct stat buffer; int result = stat(path.value().c_str(), &buffer); if (result < 0) @@ -498,10 +517,12 @@ FILE* OpenFile(const std::string& filename, const char* mode) { } FILE* OpenFile(const FilePath& filename, const char* mode) { + base::ThreadRestrictions::AssertIOAllowed(); return fopen(filename.value().c_str(), mode); } int ReadFile(const FilePath& filename, char* data, int size) { + base::ThreadRestrictions::AssertIOAllowed(); int fd = open(filename.value().c_str(), O_RDONLY); if (fd < 0) return -1; @@ -513,6 +534,7 @@ int ReadFile(const FilePath& filename, char* data, int size) { } int WriteFile(const FilePath& filename, const char* data, int size) { + base::ThreadRestrictions::AssertIOAllowed(); int fd = creat(filename.value().c_str(), 0666); if (fd < 0) return -1; @@ -540,6 +562,9 @@ int WriteFileDescriptor(const int fd, const char* data, int size) { // Gets the current working directory for the process. bool GetCurrentDirectory(FilePath* dir) { + // getcwd can return ENOENT, which implies it checks against the disk. + base::ThreadRestrictions::AssertIOAllowed(); + char system_buffer[PATH_MAX] = ""; if (!getcwd(system_buffer, sizeof(system_buffer))) { NOTREACHED(); @@ -551,6 +576,7 @@ bool GetCurrentDirectory(FilePath* dir) { // Sets the current working directory for the process. bool SetCurrentDirectory(const FilePath& path) { + base::ThreadRestrictions::AssertIOAllowed(); int ret = chdir(path.value().c_str()); return !ret; } @@ -655,6 +681,7 @@ FilePath FileEnumerator::Next() { bool FileEnumerator::ReadDirectory(std::vector<DirectoryEntryInfo>* entries, const FilePath& source, bool show_links) { + base::ThreadRestrictions::AssertIOAllowed(); DIR* dir = opendir(source.value().c_str()); if (!dir) return false; @@ -703,6 +730,8 @@ MemoryMappedFile::MemoryMappedFile() } bool MemoryMappedFile::MapFileToMemoryInternal() { + base::ThreadRestrictions::AssertIOAllowed(); + struct stat file_stat; if (fstat(file_, &file_stat) == base::kInvalidPlatformFileValue) { LOG(ERROR) << "Couldn't fstat " << file_ << ", errno " << errno; @@ -719,6 +748,8 @@ bool MemoryMappedFile::MapFileToMemoryInternal() { } void MemoryMappedFile::CloseHandles() { + base::ThreadRestrictions::AssertIOAllowed(); + if (data_ != NULL) munmap(data_, length_); if (file_ != base::kInvalidPlatformFileValue) @@ -770,6 +801,9 @@ FilePath GetHomeDir() { if (home_dir && home_dir[0]) return FilePath(home_dir); + // g_get_home_dir calls getpwent, which can fall through to LDAP calls. + base::ThreadRestrictions::AssertIOAllowed(); + home_dir = g_get_home_dir(); if (home_dir && home_dir[0]) return FilePath(home_dir); @@ -783,6 +817,7 @@ FilePath GetHomeDir() { } bool CopyFile(const FilePath& from_path, const FilePath& to_path) { + base::ThreadRestrictions::AssertIOAllowed(); int infile = open(from_path.value().c_str(), O_RDONLY); if (infile < 0) return false; diff --git a/base/shared_memory_posix.cc b/base/shared_memory_posix.cc index 7283cbd..ae814d7 100644 --- a/base/shared_memory_posix.cc +++ b/base/shared_memory_posix.cc @@ -14,6 +14,7 @@ #include "base/logging.h" #include "base/platform_thread.h" #include "base/safe_strerror_posix.h" +#include "base/thread_restrictions.h" #include "base/utf_string_conversions.h" namespace base { @@ -146,6 +147,11 @@ bool SharedMemory::CreateOrOpen(const std::string& name, int posix_flags, uint32 size) { DCHECK(mapped_file_ == -1); + // This function theoretically can block on the disk, but realistically + // the temporary files we create will just go into the buffer cache + // and be deleted before they ever make it out to disk. + base::ThreadRestrictions::ScopedAllowIO allow_io; + file_util::ScopedFILE file_closer; FILE *fp; diff --git a/base/sys_info_chromeos.cc b/base/sys_info_chromeos.cc index fec2696..e554d73 100644 --- a/base/sys_info_chromeos.cc +++ b/base/sys_info_chromeos.cc @@ -9,6 +9,7 @@ #include "base/file_util.h" #include "base/string_number_conversions.h" #include "base/string_tokenizer.h" +#include "base/thread_restrictions.h" namespace base { @@ -24,6 +25,12 @@ const char kLinuxStandardBaseReleaseFile[] = "/etc/lsb-release"; void SysInfo::OperatingSystemVersionNumbers(int32 *major_version, int32 *minor_version, int32 *bugfix_version) { + // The other implementations of SysInfo don't block on the disk. + // See http://code.google.com/p/chromium/issues/detail?id=60394 + // Perhaps the caller ought to cache this? + // Temporary allowing while we work the bug out. + base::ThreadRestrictions::ScopedAllowIO allow_io; + // TODO(cmasone): If this gets called a lot, it may kill performance. // consider using static variables to cache these values? FilePath path(kLinuxStandardBaseReleaseFile); diff --git a/base/thread_restrictions.cc b/base/thread_restrictions.cc index 1ee8eee..270d663 100644 --- a/base/thread_restrictions.cc +++ b/base/thread_restrictions.cc @@ -21,8 +21,10 @@ LazyInstance<ThreadLocalBoolean, LeakyLazyInstanceTraits<ThreadLocalBoolean> > } // anonymous namespace // static -void ThreadRestrictions::SetIOAllowed(bool allowed) { +bool ThreadRestrictions::SetIOAllowed(bool allowed) { + bool previous_allowed = g_io_disallowed.Get().Get(); g_io_disallowed.Get().Set(!allowed); + return !previous_allowed; } // static diff --git a/base/thread_restrictions.h b/base/thread_restrictions.h index c0fee58..cbdb913 100644 --- a/base/thread_restrictions.h +++ b/base/thread_restrictions.h @@ -5,6 +5,8 @@ #ifndef BASE_THREAD_RESTRICTIONS_H_ #define BASE_THREAD_RESTRICTIONS_H_ +#include "base/basictypes.h" + namespace base { // ThreadRestrictions helps protect threads that should not block from @@ -21,21 +23,43 @@ namespace base { // // ThreadRestrictions does nothing in release builds; it is debug-only. // +// Style tip: where should you put AssertIOAllowed checks? It's best +// if you put them as close to the disk access as possible, at the +// lowest level. This rule is simple to follow and helps catch all +// callers. For example, if your function GoDoSomeBlockingDiskCall() +// only calls other functions in Chrome and not fopen(), you should go +// add the AssertIOAllowed checks in the helper functions. + class ThreadRestrictions { public: + // Constructing a ScopedAllowIO temporarily allows IO for the current + // thread. Doing this is almost certainly always incorrect. This object + // is available to temporarily work around bugs. + class ScopedAllowIO { + public: + ScopedAllowIO() { previous_value_ = SetIOAllowed(true); } + ~ScopedAllowIO() { SetIOAllowed(previous_value_); } + private: + // Whether IO is allowed when the ScopedAllowIO was constructed. + bool previous_value_; + + DISALLOW_COPY_AND_ASSIGN(ScopedAllowIO); + }; #ifndef NDEBUG // Set whether the current thread to make IO calls. // Threads start out in the *allowed* state. - static void SetIOAllowed(bool allowed); + // Returns the previous value. + static bool SetIOAllowed(bool allowed); // Check whether the current thread is allowed to make IO calls, - // and DCHECK if not. + // and DCHECK if not. See the block comment above the class for + // a discussion of where to add these checks. static void AssertIOAllowed(); #else // In Release builds, inline the empty definitions of these functions so // that they can be compiled out. - static void SetIOAllowed(bool allowed) {} + static bool SetIOAllowed(bool allowed) { return true; } static void AssertIOAllowed() {} #endif diff --git a/chrome/browser/extensions/autoupdate_interceptor.cc b/chrome/browser/extensions/autoupdate_interceptor.cc index 2acd0a0..ef0091f 100644 --- a/chrome/browser/extensions/autoupdate_interceptor.cc +++ b/chrome/browser/extensions/autoupdate_interceptor.cc @@ -5,6 +5,7 @@ #include "chrome/browser/extensions/autoupdate_interceptor.h" #include "base/file_util.h" +#include "base/thread_restrictions.h" #include "chrome/browser/browser_thread.h" #include "net/url_request/url_request_test_job.h" #include "testing/gtest/include/gtest/gtest.h" @@ -40,6 +41,10 @@ URLRequestJob* AutoUpdateInterceptor::MaybeIntercept(URLRequest* request) { return NULL; } + // It's ok to do a blocking disk access on this thread; this class + // is just used for tests. + base::ThreadRestrictions::ScopedAllowIO allow_io; + // Search for this request's url, ignoring any query parameters. GURL url = request->url(); if (url.has_query()) { @@ -61,6 +66,9 @@ URLRequestJob* AutoUpdateInterceptor::MaybeIntercept(URLRequest* request) { void AutoUpdateInterceptor::SetResponse(const std::string url, const FilePath& path) { EXPECT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO)); + // It's ok to do a blocking disk access on this thread; this class + // is just used for tests. + base::ThreadRestrictions::ScopedAllowIO allow_io; GURL gurl(url); EXPECT_EQ("http", gurl.scheme()); EXPECT_EQ("localhost", gurl.host()); diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 4dc520a..8772ffd 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc @@ -12,6 +12,7 @@ #include "base/string_number_conversions.h" #include "base/string_split.h" #include "base/string_util.h" +#include "base/thread_restrictions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/gpu_process_host.h" @@ -257,6 +258,13 @@ net::ProxyScriptFetcher* IOThread::CreateAndRegisterProxyScriptFetcher( } void IOThread::Init() { +#if defined(OS_LINUX) + // TODO(evan): test and enable this on all platforms. + // 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); +#endif + BrowserProcessSubThread::Init(); DCHECK_EQ(MessageLoop::TYPE_IO, message_loop()->type()); diff --git a/chrome/browser/net/url_request_mock_http_job.cc b/chrome/browser/net/url_request_mock_http_job.cc index a35cd1e..4029605 100644 --- a/chrome/browser/net/url_request_mock_http_job.cc +++ b/chrome/browser/net/url_request_mock_http_job.cc @@ -7,6 +7,7 @@ #include "base/file_util.h" #include "base/message_loop.h" #include "base/string_util.h" +#include "base/thread_restrictions.h" #include "base/utf_string_conversions.h" #include "chrome/common/url_constants.h" #include "net/base/net_util.h" @@ -87,6 +88,10 @@ bool URLRequestMockHTTPJob::IsRedirectResponse(GURL* location, // Private const version. void URLRequestMockHTTPJob::GetResponseInfoConst( net::HttpResponseInfo* info) const { + // We have to load our headers from disk, but we only use this class + // from tests, so allow these IO operations to happen on any thread. + base::ThreadRestrictions::ScopedAllowIO allow_io; + FilePath header_file = FilePath(file_path_.value() + kMockHeaderFileSuffix); std::string raw_headers; if (!file_util::ReadFileToString(header_file, &raw_headers)) diff --git a/chrome/browser/net/url_request_mock_util.cc b/chrome/browser/net/url_request_mock_util.cc index e6531f8..b3ac398 100644 --- a/chrome/browser/net/url_request_mock_util.cc +++ b/chrome/browser/net/url_request_mock_util.cc @@ -7,6 +7,7 @@ #include <string> #include "base/path_service.h" +#include "base/thread_restrictions.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/net/url_request_failed_dns_job.h" #include "chrome/browser/net/url_request_mock_http_job.h" @@ -24,6 +25,11 @@ void SetUrlRequestMocksEnabled(bool enabled) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); if (enabled) { + // We have to look around for our helper files, but we only use + // this from tests, so allow these IO operations to happen + // anywhere. + base::ThreadRestrictions::ScopedAllowIO allow_io; + URLRequestFilter::GetInstance()->ClearHandlers(); URLRequestFailedDnsJob::AddUrlHandler(); diff --git a/chrome/browser/printing/print_dialog_cloud_uitest.cc b/chrome/browser/printing/print_dialog_cloud_uitest.cc index 1cc446d..3b57961 100644 --- a/chrome/browser/printing/print_dialog_cloud_uitest.cc +++ b/chrome/browser/printing/print_dialog_cloud_uitest.cc @@ -11,6 +11,7 @@ #include "base/file_util.h" #include "base/path_service.h" #include "base/singleton.h" +#include "base/thread_restrictions.h" #include "base/values.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_thread.h" @@ -32,7 +33,11 @@ class TestData { public: TestData() {} - char* GetTestData() { + const char* GetTestData() { + // Fetching this data blocks the IO thread, but we don't really care because + // this is a test. + base::ThreadRestrictions::ScopedAllowIO allow_io; + if (test_data_.empty()) { FilePath test_data_directory; PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory); @@ -40,7 +45,7 @@ class TestData { test_data_directory.AppendASCII("printing/cloud_print_uitest.html"); file_util::ReadFileToString(test_file, &test_data_); } - return &test_data_[0]; + return test_data_.c_str(); } private: std::string test_data_; diff --git a/chrome/browser/service/service_process_control.cc b/chrome/browser/service/service_process_control.cc index 534cc5a..6a41395 100644 --- a/chrome/browser/service/service_process_control.cc +++ b/chrome/browser/service/service_process_control.cc @@ -9,6 +9,7 @@ #include "base/process_util.h" #include "base/stl_util-inl.h" #include "base/thread.h" +#include "base/thread_restrictions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/io_thread.h" @@ -55,7 +56,14 @@ class ServiceProcessControl::Launcher void DoDetectLaunched(Task* task) { const uint32 kMaxLaunchDetectRetries = 10; - launched_ = CheckServiceProcessReady(); + { + // We should not be doing blocking disk IO from this thread! + // Temporarily allowed until we fix + // http://code.google.com/p/chromium/issues/detail?id=60207 + base::ThreadRestrictions::ScopedAllowIO allow_io; + launched_ = CheckServiceProcessReady(); + } + if (launched_ || (retry_count_ >= kMaxLaunchDetectRetries)) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(this, &Launcher::Notify, task)); diff --git a/chrome/common/extensions/extension_resource.cc b/chrome/common/extensions/extension_resource.cc index d3c5898..be22ec9 100644 --- a/chrome/common/extensions/extension_resource.cc +++ b/chrome/common/extensions/extension_resource.cc @@ -6,6 +6,7 @@ #include "base/file_util.h" #include "base/logging.h" +#include "base/thread_restrictions.h" PlatformThreadId ExtensionResource::file_thread_id_ = 0; @@ -45,6 +46,12 @@ const FilePath& ExtensionResource::GetFilePath() const { // static FilePath ExtensionResource::GetFilePathOnAnyThreadHack( const FilePath& extension_root, const FilePath& relative_path) { + // This function is a hack, and causes us to block the IO thread. + // Fixing + // http://code.google.com/p/chromium/issues/detail?id=59849 + // would also fix this. Suppress the error for now. + base::ThreadRestrictions::ScopedAllowIO allow_io; + // We need to resolve the parent references in the extension_root // path on its own because IsParent doesn't like parent references. FilePath clean_extension_root(extension_root); diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 136f138..324f50c 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -71,6 +71,7 @@ #include "base/string_number_conversions.h" #include "base/string_util.h" #include "base/stringprintf.h" +#include "base/thread_restrictions.h" #include "base/values.h" #include "net/base/address_list.h" #include "net/base/cert_status_flags.h" @@ -176,6 +177,11 @@ class NSSSSLInitSingleton { // thread-safe, and the NSS SSL library will only ever be initialized once. // The NSS SSL library will be properly shut down on program exit. void EnsureNSSSSLInit() { + // Initializing SSL causes us to do blocking IO. + // Temporarily allow it until we fix + // http://code.google.com/p/chromium/issues/detail?id=59847 + base::ThreadRestrictions::ScopedAllowIO allow_io; + Singleton<NSSSSLInitSingleton>::get(); } diff --git a/net/url_request/url_request_file_job.cc b/net/url_request/url_request_file_job.cc index 8c282ff..f9c6559 100644 --- a/net/url_request/url_request_file_job.cc +++ b/net/url_request/url_request_file_job.cc @@ -23,6 +23,7 @@ #include "base/message_loop.h" #include "base/platform_file.h" #include "base/string_util.h" +#include "base/thread_restrictions.h" #include "build/build_config.h" #include "googleurl/src/gurl.h" #include "net/base/io_buffer.h" @@ -128,8 +129,15 @@ void URLRequestFileJob::Start() { return; } #endif + + // URL requests should not block on the disk! + // http://code.google.com/p/chromium/issues/detail?id=59849 + bool exists; base::PlatformFileInfo file_info; - bool exists = file_util::GetFileInfo(file_path_, &file_info); + { + base::ThreadRestrictions::ScopedAllowIO allow_io; + exists = file_util::GetFileInfo(file_path_, &file_info); + } // Continue asynchronously. MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |