The ReadFile API on Windows invoked by the FileStream::Context class which is...
The ReadFile API on Windows invoked by the FileStream::Context class which is used by URLRequestFileJob at times completes synchronously. The FileStream::Context class is used by the URLRequestFileJob class on the IO thread. The intention here is to open the file for overlapped IO and thus complete the read and writes asynchonously. Turns out that there are cases where the ReadFile API completes synchronously which ends up blocking the IO thread. http://support.microsoft.com/kb/156932 Fix for this is to post the ReadFile call to a worker pool and inform the caller about failures etc on the calling thread. Changes in this patch are as below:- 1. The FileStream::Context::Read function posts the ReadFile call to the Worker thread pool. The entry point for this task is the static function ReadAsync. This function posts results back to the originating thread via the function ReadAsyncResult 2. Fixed the FileStreamTest.WriteRead test to not read the data in the completion callback of the stream Write function. This causes a DCHECK to fire in the MessageLoopForIO class that we are entering a nested loop which is a no no for that message pump type. This DCHECK fires because of the change on Windows to execute the ReadFile in a Worker thread pool. In any case this change is safe for all platforms. The written data is validated by reading it back in the function ValidateWrittenData in the TestWriteReadCompletionCallback class. We call this explicitly in the FileStreamTest.WriteRead test. 3. Fix the SyncableFileOperationRunnerTest.CopyAndMove test failures. This test internally initiates a ReadFile call on Windows via the FileStream::Context class for the Copy and Move test. It invokes Copy and Move and then calls MessageLoop::RunUntilIdle. This call basically runs the message loop until all pending tasks and events have been processed. This works on Windows by fluke because the ReadFile call which completes asynchronously posts IO completion tasks to the IO thread (current thread) which then get pulled out by the RunUntilIdle call. There could be cases where the ReadFile call does not post IO completion events before RunUntilIdle returns and we could see the same failures. Reason we see this with this patch is because ReadFile is now completed by a worker pool thread which basically guarantees the above scenario. Fix is to use base::RunLoop::Run() and Quit the loop when the DidFinish callback is received. I changed all places in the syncable_file_operation_runner_unittest.cc file to use base::RunLoop::Run() or base::RunLoop::RunUntilIdle() as the MessageLoop equivalents are deprecated. BUG=423948 Review URL: https://codereview.chromium.org/887863002 Cr-Commit-Position: refs/heads/master@{#314388}
Showing
Please register or sign in to comment