Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: net/base/file_stream_context_win.cc

Issue 920123002: Fix a crash in the FileStream::Context::Read code path where we were invoking a NULL callback. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Reset result_ in InvokeUserCallback Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/base/file_stream_context.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/file_stream_context.h" 5 #include "net/base/file_stream_context.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 8
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 DWORD bytes_read, 143 DWORD bytes_read,
144 DWORD error) { 144 DWORD error) {
145 DCHECK_EQ(&io_context_, context); 145 DCHECK_EQ(&io_context_, context);
146 DCHECK(!callback_.is_null()); 146 DCHECK(!callback_.is_null());
147 DCHECK(async_in_progress_); 147 DCHECK(async_in_progress_);
148 148
149 if (!async_read_initiated_) 149 if (!async_read_initiated_)
150 async_in_progress_ = false; 150 async_in_progress_ = false;
151 151
152 if (orphaned_) { 152 if (orphaned_) {
153 async_in_progress_ = false; 153 io_complete_for_read_received_ = true;
154 callback_.Reset(); 154 // If we are called due to a pending read and the asynchronous read task
155 in_flight_buf_ = NULL; 155 // has not completed we have to keep the context around until it completes.
156 CloseAndDelete(); 156 if (async_read_initiated_ && !async_read_completed_)
157 return;
158 DeleteOrphanedContext();
157 return; 159 return;
158 } 160 }
159 161
160 if (error == ERROR_HANDLE_EOF) { 162 if (error == ERROR_HANDLE_EOF) {
161 result_ = 0; 163 result_ = 0;
162 } else if (error) { 164 } else if (error) {
163 IOResult error_result = IOResult::FromOSError(error); 165 IOResult error_result = IOResult::FromOSError(error);
164 result_ = static_cast<int>(error_result.result); 166 result_ = static_cast<int>(error_result.result);
165 } else { 167 } else {
168 if (result_)
169 DCHECK_EQ(result_, static_cast<int>(bytes_read));
166 result_ = bytes_read; 170 result_ = bytes_read;
167 IncrementOffset(&io_context_.overlapped, bytes_read); 171 IncrementOffset(&io_context_.overlapped, bytes_read);
168 } 172 }
169 173
170 if (async_read_initiated_) 174 if (async_read_initiated_)
171 io_complete_for_read_received_ = true; 175 io_complete_for_read_received_ = true;
172 176
173 InvokeUserCallback(); 177 InvokeUserCallback();
174 } 178 }
175 179
176 void FileStream::Context::InvokeUserCallback() { 180 void FileStream::Context::InvokeUserCallback() {
181 if (callback_.is_null())
rvargas (doing something else) 2015/02/13 02:05:57 Should not need this.
ananta 2015/02/13 02:22:14 This might be needed if we ever receive an io comp
rvargas (doing something else) 2015/02/13 02:26:05 What do you mean for a sync read? We will receive
182 return;
177 // For an asynchonous Read operation don't invoke the user callback until 183 // For an asynchonous Read operation don't invoke the user callback until
178 // we receive the IO completion notification and the asynchronous Read 184 // we receive the IO completion notification and the asynchronous Read
179 // completion notification. 185 // completion notification.
180 if (async_read_initiated_) { 186 if (async_read_initiated_) {
181 if (!io_complete_for_read_received_ || !async_read_completed_) 187 if (!io_complete_for_read_received_ || !async_read_completed_)
182 return; 188 return;
183 async_read_initiated_ = false; 189 async_read_initiated_ = false;
184 io_complete_for_read_received_ = false; 190 io_complete_for_read_received_ = false;
185 async_read_completed_ = false; 191 async_read_completed_ = false;
186 async_in_progress_ = false; 192 async_in_progress_ = false;
187 } 193 }
194 int result = result_;
rvargas (doing something else) 2015/02/13 02:05:57 This is not needed (I was going to comment before
ananta 2015/02/13 02:22:14 Done.
195 result_ = 0;
188 CompletionCallback temp_callback = callback_; 196 CompletionCallback temp_callback = callback_;
189 callback_.Reset(); 197 callback_.Reset();
190 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_; 198 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_;
191 in_flight_buf_ = NULL; 199 in_flight_buf_ = NULL;
192 temp_callback.Run(result_); 200 temp_callback.Run(result);
201 }
202
203 void FileStream::Context::DeleteOrphanedContext() {
204 async_in_progress_ = false;
205 callback_.Reset();
206 in_flight_buf_ = NULL;
207 CloseAndDelete();
193 } 208 }
194 209
195 // static 210 // static
196 void FileStream::Context::ReadAsync( 211 void FileStream::Context::ReadAsync(
197 FileStream::Context* context, 212 FileStream::Context* context,
198 HANDLE file, 213 HANDLE file,
199 scoped_refptr<net::IOBuffer> buf, 214 scoped_refptr<net::IOBuffer> buf,
200 int buf_len, 215 int buf_len,
201 OVERLAPPED* overlapped, 216 OVERLAPPED* overlapped,
202 scoped_refptr<base::MessageLoopProxy> origin_thread_loop) { 217 scoped_refptr<base::MessageLoopProxy> origin_thread_loop) {
203 DWORD bytes_read = 0; 218 DWORD bytes_read = 0;
204 BOOL ret = ::ReadFile(file, buf->data(), buf_len, &bytes_read, overlapped); 219 BOOL ret = ::ReadFile(file, buf->data(), buf_len, &bytes_read, overlapped);
205 origin_thread_loop->PostTask( 220 origin_thread_loop->PostTask(
206 FROM_HERE, base::Bind(&FileStream::Context::ReadAsyncResult, 221 FROM_HERE,
207 base::Unretained(context), ret ? bytes_read : 0, 222 base::Bind(&FileStream::Context::ReadAsyncResult,
208 ret ? 0 : ::GetLastError())); 223 base::Unretained(context), ret, bytes_read, ::GetLastError()));
209 } 224 }
210 225
211 void FileStream::Context::ReadAsyncResult(DWORD bytes_read, DWORD os_error) { 226 void FileStream::Context::ReadAsyncResult(BOOL read_file_ret,
212 if (!os_error) 227 DWORD bytes_read,
228 DWORD os_error) {
229 async_read_completed_ = true;
rvargas (doing something else) 2015/02/13 02:05:57 nit: I think this reads better if this line goes a
ananta 2015/02/13 02:22:14 Done.
230 // If the context is orphaned and we already received the io completion
231 // notification then we should delete the context and get out.
232 if (orphaned_ && io_complete_for_read_received_) {
233 DeleteOrphanedContext();
234 return;
235 }
236
237 if (read_file_ret) {
238 DCHECK(!os_error);
rvargas (doing something else) 2015/02/13 02:05:57 This is technically out of our control. (although
ananta 2015/02/13 02:22:14 ok. Removed
213 result_ = bytes_read; 239 result_ = bytes_read;
214 240 InvokeUserCallback();
241 return;
242 }
215 IOResult error = IOResult::FromOSError(os_error); 243 IOResult error = IOResult::FromOSError(os_error);
216 if (error.os_error == ERROR_HANDLE_EOF) { 244 if (error.os_error == ERROR_HANDLE_EOF) {
217 // Report EOF by returning 0 bytes read. 245 // Report EOF by returning 0 bytes read.
218 OnIOCompleted(&io_context_, 0, error.os_error); 246 OnIOCompleted(&io_context_, 0, error.os_error);
219 } else if (error.os_error != ERROR_IO_PENDING) { 247 } else if (error.os_error != ERROR_IO_PENDING) {
220 // We don't need to inform the caller about ERROR_PENDING_IO as that was 248 // We don't need to inform the caller about ERROR_PENDING_IO as that was
221 // already done when the ReadFile call was queued to the worker pool. 249 // already done when the ReadFile call was queued to the worker pool.
222 if (error.os_error) { 250 if (error.os_error) {
223 LOG(WARNING) << "ReadFile failed: " << error.os_error; 251 LOG(WARNING) << "ReadFile failed: " << error.os_error;
224 OnIOCompleted(&io_context_, 0, error.os_error); 252 OnIOCompleted(&io_context_, 0, error.os_error);
rvargas (doing something else) 2015/02/13 02:05:57 I'd really like to simplify this code. This is the
ananta 2015/02/13 02:22:14 I removed the log and removed the multiple calls t
225 } 253 }
226 } 254 }
227 async_read_completed_ = true;
228 InvokeUserCallback();
229 } 255 }
230 256
231 } // namespace net 257 } // namespace net
OLDNEW
« no previous file with comments | « net/base/file_stream_context.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698