OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "mojo/system/raw_channel.h" | 5 #include "mojo/system/raw_channel.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
12 #include "base/debug/alias.h" | |
13 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
14 #include "base/location.h" | 13 #include "base/location.h" |
15 #include "base/logging.h" | 14 #include "base/logging.h" |
16 #include "base/macros.h" | 15 #include "base/macros.h" |
17 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
18 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
19 #include "base/synchronization/lock.h" | 18 #include "base/synchronization/lock.h" |
20 #include "base/win/windows_version.h" | 19 #include "base/win/windows_version.h" |
21 #include "mojo/embedder/platform_handle.h" | 20 #include "mojo/embedder/platform_handle.h" |
22 | 21 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 // RawChannelIOHandler receives OS notifications for I/O completion. It must | 81 // RawChannelIOHandler receives OS notifications for I/O completion. It must |
83 // be created on the I/O thread. | 82 // be created on the I/O thread. |
84 // | 83 // |
85 // It manages its own destruction. Destruction happens on the I/O thread when | 84 // It manages its own destruction. Destruction happens on the I/O thread when |
86 // all the following conditions are satisfied: | 85 // all the following conditions are satisfied: |
87 // - |DetachFromOwnerNoLock()| has been called; | 86 // - |DetachFromOwnerNoLock()| has been called; |
88 // - there is no pending read; | 87 // - there is no pending read; |
89 // - there is no pending write. | 88 // - there is no pending write. |
90 class RawChannelIOHandler : public base::MessageLoopForIO::IOHandler { | 89 class RawChannelIOHandler : public base::MessageLoopForIO::IOHandler { |
91 public: | 90 public: |
92 // TODO(yzshen): This is for debugging http://crbug.com/385795. | |
93 // This code should be removed once the issue is fixed or nothing is | |
94 // revealed by it. (No later than Aug 1, 2014.) | |
95 struct WriteStats { | |
96 WriteStats() | |
97 : write_no_lock_call(0), | |
98 schedule_write_no_lock_call(0), | |
99 os_write_call(0), | |
100 os_write_pending(0), | |
101 os_write_failure(0), | |
102 task_posted_by_schedule_write(0), | |
103 write_completion(0), | |
104 write_completion_failure(0) {} | |
105 | |
106 uint32_t write_no_lock_call; | |
107 uint32_t schedule_write_no_lock_call; | |
108 uint32_t os_write_call; | |
109 uint32_t os_write_pending; | |
110 uint32_t os_write_failure; | |
111 uint32_t task_posted_by_schedule_write; | |
112 uint32_t write_completion; | |
113 uint32_t write_completion_failure; | |
114 }; | |
115 | |
116 RawChannelIOHandler(RawChannelWin* owner, | 91 RawChannelIOHandler(RawChannelWin* owner, |
117 embedder::ScopedPlatformHandle handle); | 92 embedder::ScopedPlatformHandle handle); |
118 | 93 |
119 HANDLE handle() const { return handle_.get().handle; } | 94 HANDLE handle() const { return handle_.get().handle; } |
120 | 95 |
121 // The following methods are only called by the owner on the I/O thread. | 96 // The following methods are only called by the owner on the I/O thread. |
122 bool pending_read() const; | 97 bool pending_read() const; |
123 base::MessageLoopForIO::IOContext* read_context(); | 98 base::MessageLoopForIO::IOContext* read_context(); |
124 // Instructs the object to wait for an |OnIOCompleted()| notification. | 99 // Instructs the object to wait for an |OnIOCompleted()| notification. |
125 void OnPendingReadStarted(); | 100 void OnPendingReadStarted(); |
126 | 101 |
127 // The following methods are only called by the owner under | 102 // The following methods are only called by the owner under |
128 // |owner_->write_lock()|. | 103 // |owner_->write_lock()|. |
129 bool pending_write_no_lock() const; | 104 bool pending_write_no_lock() const; |
130 base::MessageLoopForIO::IOContext* write_context_no_lock(); | 105 base::MessageLoopForIO::IOContext* write_context_no_lock(); |
131 // Instructs the object to wait for an |OnIOCompleted()| notification. | 106 // Instructs the object to wait for an |OnIOCompleted()| notification. |
132 void OnPendingWriteStartedNoLock(); | 107 void OnPendingWriteStartedNoLock(); |
133 WriteStats* write_stats_no_lock(); | |
134 | 108 |
135 // |base::MessageLoopForIO::IOHandler| implementation: | 109 // |base::MessageLoopForIO::IOHandler| implementation: |
136 // Must be called on the I/O thread. It could be called before or after | 110 // Must be called on the I/O thread. It could be called before or after |
137 // detached from the owner. | 111 // detached from the owner. |
138 virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context, | 112 virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context, |
139 DWORD bytes_transferred, | 113 DWORD bytes_transferred, |
140 DWORD error) OVERRIDE; | 114 DWORD error) OVERRIDE; |
141 | 115 |
142 // Must be called on the I/O thread under |owner_->write_lock()|. | 116 // Must be called on the I/O thread under |owner_->write_lock()|. |
143 // After this call, the owner must not make any further calls on this | 117 // After this call, the owner must not make any further calls on this |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 | 149 |
176 bool pending_read_; | 150 bool pending_read_; |
177 base::MessageLoopForIO::IOContext read_context_; | 151 base::MessageLoopForIO::IOContext read_context_; |
178 | 152 |
179 // The following members must be used under |owner_->write_lock()| while the | 153 // The following members must be used under |owner_->write_lock()| while the |
180 // object is still attached to the owner, and only on the I/O thread | 154 // object is still attached to the owner, and only on the I/O thread |
181 // afterwards. | 155 // afterwards. |
182 bool pending_write_; | 156 bool pending_write_; |
183 base::MessageLoopForIO::IOContext write_context_; | 157 base::MessageLoopForIO::IOContext write_context_; |
184 | 158 |
185 WriteStats write_stats_; | |
186 | |
187 DISALLOW_COPY_AND_ASSIGN(RawChannelIOHandler); | 159 DISALLOW_COPY_AND_ASSIGN(RawChannelIOHandler); |
188 }; | 160 }; |
189 | 161 |
190 // |RawChannel| private methods: | 162 // |RawChannel| private methods: |
191 virtual IOResult Read(size_t* bytes_read) OVERRIDE; | 163 virtual IOResult Read(size_t* bytes_read) OVERRIDE; |
192 virtual IOResult ScheduleRead() OVERRIDE; | 164 virtual IOResult ScheduleRead() OVERRIDE; |
193 virtual embedder::ScopedPlatformHandleVectorPtr GetReadPlatformHandles( | 165 virtual embedder::ScopedPlatformHandleVectorPtr GetReadPlatformHandles( |
194 size_t num_platform_handles, | 166 size_t num_platform_handles, |
195 const void* platform_handle_table) OVERRIDE; | 167 const void* platform_handle_table) OVERRIDE; |
196 virtual IOResult WriteNoLock(size_t* platform_handles_written, | 168 virtual IOResult WriteNoLock(size_t* platform_handles_written, |
(...skipping 23 matching lines...) Expand all Loading... |
220 pending_write_(false) { | 192 pending_write_(false) { |
221 memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped)); | 193 memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped)); |
222 read_context_.handler = this; | 194 read_context_.handler = this; |
223 memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped)); | 195 memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped)); |
224 write_context_.handler = this; | 196 write_context_.handler = this; |
225 | 197 |
226 owner_->message_loop_for_io()->RegisterIOHandler(handle_.get().handle, this); | 198 owner_->message_loop_for_io()->RegisterIOHandler(handle_.get().handle, this); |
227 } | 199 } |
228 | 200 |
229 RawChannelWin::RawChannelIOHandler::~RawChannelIOHandler() { | 201 RawChannelWin::RawChannelIOHandler::~RawChannelIOHandler() { |
230 CHECK(ShouldSelfDestruct()); | 202 DCHECK(ShouldSelfDestruct()); |
231 | |
232 VLOG(4) << "write_no_lock_call: " << write_stats_.write_no_lock_call << "\n" | |
233 << "schedule_write_no_lock_call: " | |
234 << write_stats_.schedule_write_no_lock_call << "\n" | |
235 << "os_write_call: " << write_stats_.os_write_call << "\n" | |
236 << "os_write_pending: " << write_stats_.os_write_pending << "\n" | |
237 << "os_write_failure: " << write_stats_.os_write_failure << "\n" | |
238 << "task_posted_by_schedule_write: " | |
239 << write_stats_.task_posted_by_schedule_write << "\n" | |
240 << "write_completion: " << write_stats_.write_completion << "\n" | |
241 << "write_completion_failure: " | |
242 << write_stats_.write_completion_failure << "\n"; | |
243 } | 203 } |
244 | 204 |
245 bool RawChannelWin::RawChannelIOHandler::pending_read() const { | 205 bool RawChannelWin::RawChannelIOHandler::pending_read() const { |
246 CHECK(owner_); | 206 DCHECK(owner_); |
247 CHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); | 207 DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); |
248 return pending_read_; | 208 return pending_read_; |
249 } | 209 } |
250 | 210 |
251 base::MessageLoopForIO::IOContext* | 211 base::MessageLoopForIO::IOContext* |
252 RawChannelWin::RawChannelIOHandler::read_context() { | 212 RawChannelWin::RawChannelIOHandler::read_context() { |
253 CHECK(owner_); | 213 DCHECK(owner_); |
254 CHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); | 214 DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); |
255 return &read_context_; | 215 return &read_context_; |
256 } | 216 } |
257 | 217 |
258 void RawChannelWin::RawChannelIOHandler::OnPendingReadStarted() { | 218 void RawChannelWin::RawChannelIOHandler::OnPendingReadStarted() { |
259 CHECK(owner_); | 219 DCHECK(owner_); |
260 CHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); | 220 DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); |
261 CHECK(!pending_read_); | 221 DCHECK(!pending_read_); |
262 pending_read_ = true; | 222 pending_read_ = true; |
263 } | 223 } |
264 | 224 |
265 bool RawChannelWin::RawChannelIOHandler::pending_write_no_lock() const { | 225 bool RawChannelWin::RawChannelIOHandler::pending_write_no_lock() const { |
266 CHECK(owner_); | 226 DCHECK(owner_); |
267 owner_->write_lock().AssertAcquired(); | 227 owner_->write_lock().AssertAcquired(); |
268 return pending_write_; | 228 return pending_write_; |
269 } | 229 } |
270 | 230 |
271 base::MessageLoopForIO::IOContext* | 231 base::MessageLoopForIO::IOContext* |
272 RawChannelWin::RawChannelIOHandler::write_context_no_lock() { | 232 RawChannelWin::RawChannelIOHandler::write_context_no_lock() { |
273 CHECK(owner_); | 233 DCHECK(owner_); |
274 owner_->write_lock().AssertAcquired(); | 234 owner_->write_lock().AssertAcquired(); |
275 return &write_context_; | 235 return &write_context_; |
276 } | 236 } |
277 | 237 |
278 void RawChannelWin::RawChannelIOHandler::OnPendingWriteStartedNoLock() { | 238 void RawChannelWin::RawChannelIOHandler::OnPendingWriteStartedNoLock() { |
279 CHECK(owner_); | 239 DCHECK(owner_); |
280 owner_->write_lock().AssertAcquired(); | 240 owner_->write_lock().AssertAcquired(); |
281 CHECK(!pending_write_); | 241 DCHECK(!pending_write_); |
282 pending_write_ = true; | 242 pending_write_ = true; |
283 } | 243 } |
284 | 244 |
285 RawChannelWin::RawChannelIOHandler::WriteStats* | |
286 RawChannelWin::RawChannelIOHandler::write_stats_no_lock() { | |
287 CHECK(owner_); | |
288 owner_->write_lock().AssertAcquired(); | |
289 return &write_stats_; | |
290 } | |
291 | |
292 void RawChannelWin::RawChannelIOHandler::OnIOCompleted( | 245 void RawChannelWin::RawChannelIOHandler::OnIOCompleted( |
293 base::MessageLoopForIO::IOContext* context, | 246 base::MessageLoopForIO::IOContext* context, |
294 DWORD bytes_transferred, | 247 DWORD bytes_transferred, |
295 DWORD error) { | 248 DWORD error) { |
296 CHECK(!owner_ || | 249 DCHECK(!owner_ || |
297 base::MessageLoop::current() == owner_->message_loop_for_io()); | 250 base::MessageLoop::current() == owner_->message_loop_for_io()); |
298 | 251 |
299 { | 252 { |
300 // Suppress self-destruction inside |OnReadCompleted()|, etc. (in case they | 253 // Suppress self-destruction inside |OnReadCompleted()|, etc. (in case they |
301 // result in a call to |Shutdown()|). | 254 // result in a call to |Shutdown()|). |
302 base::AutoReset<bool> resetter(&suppress_self_destruct_, true); | 255 base::AutoReset<bool> resetter(&suppress_self_destruct_, true); |
303 | 256 |
304 if (context == &read_context_) | 257 if (context == &read_context_) |
305 OnReadCompleted(bytes_transferred, error); | 258 OnReadCompleted(bytes_transferred, error); |
306 else if (context == &write_context_) | 259 else if (context == &write_context_) |
307 OnWriteCompleted(bytes_transferred, error); | 260 OnWriteCompleted(bytes_transferred, error); |
308 else | 261 else |
309 NOTREACHED(); | 262 NOTREACHED(); |
310 } | 263 } |
311 | 264 |
312 if (ShouldSelfDestruct()) | 265 if (ShouldSelfDestruct()) |
313 delete this; | 266 delete this; |
314 } | 267 } |
315 | 268 |
316 void RawChannelWin::RawChannelIOHandler::DetachFromOwnerNoLock( | 269 void RawChannelWin::RawChannelIOHandler::DetachFromOwnerNoLock( |
317 scoped_ptr<ReadBuffer> read_buffer, | 270 scoped_ptr<ReadBuffer> read_buffer, |
318 scoped_ptr<WriteBuffer> write_buffer) { | 271 scoped_ptr<WriteBuffer> write_buffer) { |
319 CHECK(owner_); | 272 DCHECK(owner_); |
320 CHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); | 273 DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); |
321 owner_->write_lock().AssertAcquired(); | 274 owner_->write_lock().AssertAcquired(); |
322 | 275 |
323 // If read/write is pending, we have to retain the corresponding buffer. | 276 // If read/write is pending, we have to retain the corresponding buffer. |
324 if (pending_read_) | 277 if (pending_read_) |
325 preserved_read_buffer_after_detach_ = read_buffer.Pass(); | 278 preserved_read_buffer_after_detach_ = read_buffer.Pass(); |
326 if (pending_write_) | 279 if (pending_write_) |
327 preserved_write_buffer_after_detach_ = write_buffer.Pass(); | 280 preserved_write_buffer_after_detach_ = write_buffer.Pass(); |
328 | 281 |
329 owner_ = NULL; | 282 owner_ = NULL; |
330 if (ShouldSelfDestruct()) | 283 if (ShouldSelfDestruct()) |
331 delete this; | 284 delete this; |
332 } | 285 } |
333 | 286 |
334 bool RawChannelWin::RawChannelIOHandler::ShouldSelfDestruct() const { | 287 bool RawChannelWin::RawChannelIOHandler::ShouldSelfDestruct() const { |
335 if (owner_ || suppress_self_destruct_) | 288 if (owner_ || suppress_self_destruct_) |
336 return false; | 289 return false; |
337 | 290 |
338 // Note: Detached, hence no lock needed for |pending_write_|. | 291 // Note: Detached, hence no lock needed for |pending_write_|. |
339 return !pending_read_ && !pending_write_; | 292 return !pending_read_ && !pending_write_; |
340 } | 293 } |
341 | 294 |
342 void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read, | 295 void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read, |
343 DWORD error) { | 296 DWORD error) { |
344 CHECK(!owner_ || | 297 DCHECK(!owner_ || |
345 base::MessageLoop::current() == owner_->message_loop_for_io()); | 298 base::MessageLoop::current() == owner_->message_loop_for_io()); |
346 CHECK(suppress_self_destruct_); | 299 DCHECK(suppress_self_destruct_); |
347 | 300 |
348 CHECK(pending_read_); | 301 CHECK(pending_read_); |
349 pending_read_ = false; | 302 pending_read_ = false; |
350 if (!owner_) | 303 if (!owner_) |
351 return; | 304 return; |
352 | 305 |
353 if (error != ERROR_SUCCESS) { | 306 if (error != ERROR_SUCCESS) { |
354 CHECK_EQ(bytes_read, 0u); | 307 DCHECK_EQ(bytes_read, 0u); |
355 LOG_IF(ERROR, error != ERROR_BROKEN_PIPE) | 308 LOG_IF(ERROR, error != ERROR_BROKEN_PIPE) |
356 << "ReadFile: " << logging::SystemErrorCodeToString(error); | 309 << "ReadFile: " << logging::SystemErrorCodeToString(error); |
357 owner_->OnReadCompleted(false, 0); | 310 owner_->OnReadCompleted(false, 0); |
358 } else { | 311 } else { |
359 CHECK_GT(bytes_read, 0u); | 312 DCHECK_GT(bytes_read, 0u); |
360 owner_->OnReadCompleted(true, bytes_read); | 313 owner_->OnReadCompleted(true, bytes_read); |
361 } | 314 } |
362 } | 315 } |
363 | 316 |
364 void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written, | 317 void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written, |
365 DWORD error) { | 318 DWORD error) { |
366 CHECK(!owner_ || | 319 DCHECK(!owner_ || |
367 base::MessageLoop::current() == owner_->message_loop_for_io()); | 320 base::MessageLoop::current() == owner_->message_loop_for_io()); |
368 CHECK(suppress_self_destruct_); | 321 DCHECK(suppress_self_destruct_); |
369 | |
370 WriteStats stack_copy; | |
371 base::debug::Alias(&stack_copy); | |
372 | 322 |
373 if (!owner_) { | 323 if (!owner_) { |
374 // No lock needed. | 324 // No lock needed. |
375 | |
376 write_stats_.write_completion++; | |
377 if (error != ERROR_SUCCESS) | |
378 write_stats_.write_completion_failure++; | |
379 stack_copy = write_stats_; | |
380 | |
381 CHECK(pending_write_); | 325 CHECK(pending_write_); |
382 pending_write_ = false; | 326 pending_write_ = false; |
383 return; | 327 return; |
384 } | 328 } |
385 | 329 |
386 { | 330 { |
387 base::AutoLock locker(owner_->write_lock()); | 331 base::AutoLock locker(owner_->write_lock()); |
388 | |
389 write_stats_.write_completion++; | |
390 if (error != ERROR_SUCCESS) | |
391 write_stats_.write_completion_failure++; | |
392 stack_copy = write_stats_; | |
393 | |
394 CHECK(pending_write_); | 332 CHECK(pending_write_); |
395 pending_write_ = false; | 333 pending_write_ = false; |
396 } | 334 } |
397 | 335 |
398 if (error != ERROR_SUCCESS) { | 336 if (error != ERROR_SUCCESS) { |
399 LOG(ERROR) << "WriteFile: " << logging::SystemErrorCodeToString(error); | 337 LOG(ERROR) << "WriteFile: " << logging::SystemErrorCodeToString(error); |
400 owner_->OnWriteCompleted(false, 0, 0); | 338 owner_->OnWriteCompleted(false, 0, 0); |
401 } else { | 339 } else { |
402 owner_->OnWriteCompleted(true, 0, bytes_written); | 340 owner_->OnWriteCompleted(true, 0, bytes_written); |
403 } | 341 } |
404 } | 342 } |
405 | 343 |
406 RawChannelWin::RawChannelWin(embedder::ScopedPlatformHandle handle) | 344 RawChannelWin::RawChannelWin(embedder::ScopedPlatformHandle handle) |
407 : handle_(handle.Pass()), | 345 : handle_(handle.Pass()), |
408 io_handler_(NULL), | 346 io_handler_(NULL), |
409 skip_completion_port_on_success_( | 347 skip_completion_port_on_success_( |
410 g_vista_or_higher_functions.Get().is_vista_or_higher()) { | 348 g_vista_or_higher_functions.Get().is_vista_or_higher()) { |
411 CHECK(handle_.is_valid()); | 349 DCHECK(handle_.is_valid()); |
412 } | 350 } |
413 | 351 |
414 RawChannelWin::~RawChannelWin() { | 352 RawChannelWin::~RawChannelWin() { |
415 CHECK(!io_handler_); | 353 DCHECK(!io_handler_); |
416 } | 354 } |
417 | 355 |
418 size_t RawChannelWin::GetSerializedPlatformHandleSize() const { | 356 size_t RawChannelWin::GetSerializedPlatformHandleSize() const { |
419 // TODO(vtl): Implement. | 357 // TODO(vtl): Implement. |
420 return 0; | 358 return 0; |
421 } | 359 } |
422 | 360 |
423 RawChannel::IOResult RawChannelWin::Read(size_t* bytes_read) { | 361 RawChannel::IOResult RawChannelWin::Read(size_t* bytes_read) { |
424 CHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); | 362 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
425 CHECK(io_handler_); | 363 DCHECK(io_handler_); |
426 CHECK(!io_handler_->pending_read()); | 364 DCHECK(!io_handler_->pending_read()); |
427 | 365 |
428 char* buffer = NULL; | 366 char* buffer = NULL; |
429 size_t bytes_to_read = 0; | 367 size_t bytes_to_read = 0; |
430 read_buffer()->GetBuffer(&buffer, &bytes_to_read); | 368 read_buffer()->GetBuffer(&buffer, &bytes_to_read); |
431 | 369 |
432 DWORD bytes_read_dword = 0; | 370 DWORD bytes_read_dword = 0; |
433 BOOL result = ReadFile(io_handler_->handle(), | 371 BOOL result = ReadFile(io_handler_->handle(), |
434 buffer, | 372 buffer, |
435 static_cast<DWORD>(bytes_to_read), | 373 static_cast<DWORD>(bytes_to_read), |
436 &bytes_read_dword, | 374 &bytes_read_dword, |
437 &io_handler_->read_context()->overlapped); | 375 &io_handler_->read_context()->overlapped); |
438 if (!result) { | 376 if (!result) { |
439 CHECK_EQ(bytes_read_dword, 0u); | 377 DCHECK_EQ(bytes_read_dword, 0u); |
440 DWORD error = GetLastError(); | 378 DWORD error = GetLastError(); |
441 if (error != ERROR_IO_PENDING) { | 379 if (error != ERROR_IO_PENDING) { |
442 LOG_IF(ERROR, error != ERROR_BROKEN_PIPE) | 380 LOG_IF(ERROR, error != ERROR_BROKEN_PIPE) |
443 << "ReadFile: " << logging::SystemErrorCodeToString(error); | 381 << "ReadFile: " << logging::SystemErrorCodeToString(error); |
444 return IO_FAILED; | 382 return IO_FAILED; |
445 } | 383 } |
446 } | 384 } |
447 | 385 |
448 if (result && skip_completion_port_on_success_) { | 386 if (result && skip_completion_port_on_success_) { |
449 *bytes_read = bytes_read_dword; | 387 *bytes_read = bytes_read_dword; |
450 return IO_SUCCEEDED; | 388 return IO_SUCCEEDED; |
451 } | 389 } |
452 | 390 |
453 // If the read is pending or the read has succeeded but we don't skip | 391 // If the read is pending or the read has succeeded but we don't skip |
454 // completion port on success, instruct |io_handler_| to wait for the | 392 // completion port on success, instruct |io_handler_| to wait for the |
455 // completion packet. | 393 // completion packet. |
456 // | 394 // |
457 // TODO(yzshen): It seems there isn't document saying that all error cases | 395 // TODO(yzshen): It seems there isn't document saying that all error cases |
458 // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion | 396 // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion |
459 // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()| | 397 // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()| |
460 // will crash so we will learn about it. | 398 // will crash so we will learn about it. |
461 | 399 |
462 io_handler_->OnPendingReadStarted(); | 400 io_handler_->OnPendingReadStarted(); |
463 return IO_PENDING; | 401 return IO_PENDING; |
464 } | 402 } |
465 | 403 |
466 RawChannel::IOResult RawChannelWin::ScheduleRead() { | 404 RawChannel::IOResult RawChannelWin::ScheduleRead() { |
467 CHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); | 405 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
468 CHECK(io_handler_); | 406 DCHECK(io_handler_); |
469 CHECK(!io_handler_->pending_read()); | 407 DCHECK(!io_handler_->pending_read()); |
470 | 408 |
471 size_t bytes_read = 0; | 409 size_t bytes_read = 0; |
472 IOResult io_result = Read(&bytes_read); | 410 IOResult io_result = Read(&bytes_read); |
473 if (io_result == IO_SUCCEEDED) { | 411 if (io_result == IO_SUCCEEDED) { |
474 CHECK(skip_completion_port_on_success_); | 412 DCHECK(skip_completion_port_on_success_); |
475 | 413 |
476 // We have finished reading successfully. Queue a notification manually. | 414 // We have finished reading successfully. Queue a notification manually. |
477 io_handler_->OnPendingReadStarted(); | 415 io_handler_->OnPendingReadStarted(); |
478 // |io_handler_| won't go away before the task is run, so it is safe to use | 416 // |io_handler_| won't go away before the task is run, so it is safe to use |
479 // |base::Unretained()|. | 417 // |base::Unretained()|. |
480 message_loop_for_io()->PostTask( | 418 message_loop_for_io()->PostTask( |
481 FROM_HERE, | 419 FROM_HERE, |
482 base::Bind(&RawChannelIOHandler::OnIOCompleted, | 420 base::Bind(&RawChannelIOHandler::OnIOCompleted, |
483 base::Unretained(io_handler_), | 421 base::Unretained(io_handler_), |
484 base::Unretained(io_handler_->read_context()), | 422 base::Unretained(io_handler_->read_context()), |
(...skipping 11 matching lines...) Expand all Loading... |
496 // TODO(vtl): Implement. | 434 // TODO(vtl): Implement. |
497 NOTIMPLEMENTED(); | 435 NOTIMPLEMENTED(); |
498 return embedder::ScopedPlatformHandleVectorPtr(); | 436 return embedder::ScopedPlatformHandleVectorPtr(); |
499 } | 437 } |
500 | 438 |
501 RawChannel::IOResult RawChannelWin::WriteNoLock( | 439 RawChannel::IOResult RawChannelWin::WriteNoLock( |
502 size_t* platform_handles_written, | 440 size_t* platform_handles_written, |
503 size_t* bytes_written) { | 441 size_t* bytes_written) { |
504 write_lock().AssertAcquired(); | 442 write_lock().AssertAcquired(); |
505 | 443 |
506 RawChannelIOHandler::WriteStats stack_copy( | 444 DCHECK(io_handler_); |
507 *io_handler_->write_stats_no_lock()); | 445 DCHECK(!io_handler_->pending_write_no_lock()); |
508 base::debug::Alias(&stack_copy); | |
509 | |
510 io_handler_->write_stats_no_lock()->write_no_lock_call++; | |
511 stack_copy.write_no_lock_call++; | |
512 | |
513 CHECK(io_handler_); | |
514 CHECK(!io_handler_->pending_write_no_lock()); | |
515 | 446 |
516 if (write_buffer_no_lock()->HavePlatformHandlesToSend()) { | 447 if (write_buffer_no_lock()->HavePlatformHandlesToSend()) { |
517 // TODO(vtl): Implement. | 448 // TODO(vtl): Implement. |
518 NOTIMPLEMENTED(); | 449 NOTIMPLEMENTED(); |
519 } | 450 } |
520 | 451 |
521 std::vector<WriteBuffer::Buffer> buffers; | 452 std::vector<WriteBuffer::Buffer> buffers; |
522 write_buffer_no_lock()->GetBuffers(&buffers); | 453 write_buffer_no_lock()->GetBuffers(&buffers); |
523 CHECK(!buffers.empty()); | 454 DCHECK(!buffers.empty()); |
524 | |
525 io_handler_->write_stats_no_lock()->os_write_call++; | |
526 stack_copy.os_write_call++; | |
527 | 455 |
528 // TODO(yzshen): Handle multi-segment writes more efficiently. | 456 // TODO(yzshen): Handle multi-segment writes more efficiently. |
529 DWORD bytes_written_dword = 0; | 457 DWORD bytes_written_dword = 0; |
530 BOOL result = WriteFile(io_handler_->handle(), | 458 BOOL result = WriteFile(io_handler_->handle(), |
531 buffers[0].addr, | 459 buffers[0].addr, |
532 static_cast<DWORD>(buffers[0].size), | 460 static_cast<DWORD>(buffers[0].size), |
533 &bytes_written_dword, | 461 &bytes_written_dword, |
534 &io_handler_->write_context_no_lock()->overlapped); | 462 &io_handler_->write_context_no_lock()->overlapped); |
535 | 463 if (!result && GetLastError() != ERROR_IO_PENDING) { |
536 if (!result) { | 464 PLOG(ERROR) << "WriteFile"; |
537 if (GetLastError() == ERROR_IO_PENDING) { | 465 return IO_FAILED; |
538 io_handler_->write_stats_no_lock()->os_write_pending++; | |
539 stack_copy.os_write_pending++; | |
540 } else { | |
541 io_handler_->write_stats_no_lock()->os_write_failure++; | |
542 stack_copy.os_write_failure++; | |
543 | |
544 PLOG(ERROR) << "WriteFile"; | |
545 return IO_FAILED; | |
546 } | |
547 } | 466 } |
548 | 467 |
549 if (result && skip_completion_port_on_success_) { | 468 if (result && skip_completion_port_on_success_) { |
550 *platform_handles_written = 0; | 469 *platform_handles_written = 0; |
551 *bytes_written = bytes_written_dword; | 470 *bytes_written = bytes_written_dword; |
552 return IO_SUCCEEDED; | 471 return IO_SUCCEEDED; |
553 } | 472 } |
554 | 473 |
555 // If the write is pending or the write has succeeded but we don't skip | 474 // If the write is pending or the write has succeeded but we don't skip |
556 // completion port on success, instruct |io_handler_| to wait for the | 475 // completion port on success, instruct |io_handler_| to wait for the |
557 // completion packet. | 476 // completion packet. |
558 // | 477 // |
559 // TODO(yzshen): it seems there isn't document saying that all error cases | 478 // TODO(yzshen): it seems there isn't document saying that all error cases |
560 // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion | 479 // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion |
561 // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()| | 480 // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()| |
562 // will crash so we will learn about it. | 481 // will crash so we will learn about it. |
563 | 482 |
564 io_handler_->OnPendingWriteStartedNoLock(); | 483 io_handler_->OnPendingWriteStartedNoLock(); |
565 return IO_PENDING; | 484 return IO_PENDING; |
566 } | 485 } |
567 | 486 |
568 RawChannel::IOResult RawChannelWin::ScheduleWriteNoLock() { | 487 RawChannel::IOResult RawChannelWin::ScheduleWriteNoLock() { |
569 write_lock().AssertAcquired(); | 488 write_lock().AssertAcquired(); |
570 | 489 |
571 RawChannelIOHandler::WriteStats stack_copy( | 490 DCHECK(io_handler_); |
572 *io_handler_->write_stats_no_lock()); | 491 DCHECK(!io_handler_->pending_write_no_lock()); |
573 base::debug::Alias(&stack_copy); | |
574 | |
575 io_handler_->write_stats_no_lock()->schedule_write_no_lock_call++; | |
576 stack_copy.schedule_write_no_lock_call++; | |
577 | |
578 CHECK(io_handler_); | |
579 CHECK(!io_handler_->pending_write_no_lock()); | |
580 | 492 |
581 // TODO(vtl): Do something with |platform_handles_written|. | 493 // TODO(vtl): Do something with |platform_handles_written|. |
582 size_t platform_handles_written = 0; | 494 size_t platform_handles_written = 0; |
583 size_t bytes_written = 0; | 495 size_t bytes_written = 0; |
584 IOResult io_result = WriteNoLock(&platform_handles_written, &bytes_written); | 496 IOResult io_result = WriteNoLock(&platform_handles_written, &bytes_written); |
585 if (io_result == IO_SUCCEEDED) { | 497 if (io_result == IO_SUCCEEDED) { |
586 CHECK(skip_completion_port_on_success_); | 498 DCHECK(skip_completion_port_on_success_); |
587 | 499 |
588 // We have finished writing successfully. Queue a notification manually. | 500 // We have finished writing successfully. Queue a notification manually. |
589 io_handler_->OnPendingWriteStartedNoLock(); | 501 io_handler_->OnPendingWriteStartedNoLock(); |
590 | |
591 io_handler_->write_stats_no_lock()->task_posted_by_schedule_write++; | |
592 stack_copy.task_posted_by_schedule_write++; | |
593 | |
594 // |io_handler_| won't go away before that task is run, so it is safe to use | 502 // |io_handler_| won't go away before that task is run, so it is safe to use |
595 // |base::Unretained()|. | 503 // |base::Unretained()|. |
596 message_loop_for_io()->PostTask( | 504 message_loop_for_io()->PostTask( |
597 FROM_HERE, | 505 FROM_HERE, |
598 base::Bind(&RawChannelIOHandler::OnIOCompleted, | 506 base::Bind(&RawChannelIOHandler::OnIOCompleted, |
599 base::Unretained(io_handler_), | 507 base::Unretained(io_handler_), |
600 base::Unretained(io_handler_->write_context_no_lock()), | 508 base::Unretained(io_handler_->write_context_no_lock()), |
601 static_cast<DWORD>(bytes_written), | 509 static_cast<DWORD>(bytes_written), |
602 ERROR_SUCCESS)); | 510 ERROR_SUCCESS)); |
603 return IO_PENDING; | 511 return IO_PENDING; |
604 } | 512 } |
605 | 513 |
606 return io_result; | 514 return io_result; |
607 } | 515 } |
608 | 516 |
609 bool RawChannelWin::OnInit() { | 517 bool RawChannelWin::OnInit() { |
610 CHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); | 518 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
611 | 519 |
612 CHECK(handle_.is_valid()); | 520 DCHECK(handle_.is_valid()); |
613 if (skip_completion_port_on_success_ && | 521 if (skip_completion_port_on_success_ && |
614 !g_vista_or_higher_functions.Get().SetFileCompletionNotificationModes( | 522 !g_vista_or_higher_functions.Get().SetFileCompletionNotificationModes( |
615 handle_.get().handle, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { | 523 handle_.get().handle, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { |
616 return false; | 524 return false; |
617 } | 525 } |
618 | 526 |
619 CHECK(!io_handler_); | 527 DCHECK(!io_handler_); |
620 io_handler_ = new RawChannelIOHandler(this, handle_.Pass()); | 528 io_handler_ = new RawChannelIOHandler(this, handle_.Pass()); |
621 | 529 |
622 return true; | 530 return true; |
623 } | 531 } |
624 | 532 |
625 void RawChannelWin::OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer, | 533 void RawChannelWin::OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer, |
626 scoped_ptr<WriteBuffer> write_buffer) { | 534 scoped_ptr<WriteBuffer> write_buffer) { |
627 CHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); | 535 DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
628 CHECK(io_handler_); | 536 DCHECK(io_handler_); |
629 | 537 |
630 write_lock().AssertAcquired(); | 538 write_lock().AssertAcquired(); |
631 | 539 |
632 if (io_handler_->pending_read() || io_handler_->pending_write_no_lock()) { | 540 if (io_handler_->pending_read() || io_handler_->pending_write_no_lock()) { |
633 // |io_handler_| will be alive until pending read/write (if any) completes. | 541 // |io_handler_| will be alive until pending read/write (if any) completes. |
634 // Call |CancelIoEx()| or |CancelIo()| so that resources can be freed up as | 542 // Call |CancelIoEx()| or |CancelIo()| so that resources can be freed up as |
635 // soon as possible. | 543 // soon as possible. |
636 // Note: |CancelIo()| only cancels read/write requests started from this | 544 // Note: |CancelIo()| only cancels read/write requests started from this |
637 // thread. | 545 // thread. |
638 if (g_vista_or_higher_functions.Get().is_vista_or_higher()) | 546 if (g_vista_or_higher_functions.Get().is_vista_or_higher()) |
(...skipping 12 matching lines...) Expand all Loading... |
651 | 559 |
652 // Static factory method declared in raw_channel.h. | 560 // Static factory method declared in raw_channel.h. |
653 // static | 561 // static |
654 scoped_ptr<RawChannel> RawChannel::Create( | 562 scoped_ptr<RawChannel> RawChannel::Create( |
655 embedder::ScopedPlatformHandle handle) { | 563 embedder::ScopedPlatformHandle handle) { |
656 return scoped_ptr<RawChannel>(new RawChannelWin(handle.Pass())); | 564 return scoped_ptr<RawChannel>(new RawChannelWin(handle.Pass())); |
657 } | 565 } |
658 | 566 |
659 } // namespace system | 567 } // namespace system |
660 } // namespace mojo | 568 } // namespace mojo |
OLD | NEW |