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