summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorevan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-23 05:19:20 +0000
committerevan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-23 05:19:20 +0000
commitba74b0d2f492a1a7a310af5e69fa7a0812ce6f52 (patch)
treeeacff9788a950e58118148b5cae3f236840a49b0
parent3c24a4682e05dc4496c0a9d898872ac39d142817 (diff)
downloadchromium_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.cc35
-rw-r--r--base/shared_memory_posix.cc6
-rw-r--r--base/sys_info_chromeos.cc7
-rw-r--r--base/thread_restrictions.cc4
-rw-r--r--base/thread_restrictions.h30
-rw-r--r--chrome/browser/extensions/autoupdate_interceptor.cc8
-rw-r--r--chrome/browser/io_thread.cc8
-rw-r--r--chrome/browser/net/url_request_mock_http_job.cc5
-rw-r--r--chrome/browser/net/url_request_mock_util.cc6
-rw-r--r--chrome/browser/printing/print_dialog_cloud_uitest.cc9
-rw-r--r--chrome/browser/service/service_process_control.cc10
-rw-r--r--chrome/common/extensions/extension_resource.cc7
-rw-r--r--net/socket/ssl_client_socket_nss.cc6
-rw-r--r--net/url_request/url_request_file_job.cc10
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(