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/basictypes.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/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
13 #include "base/location.h" | 13 #include "base/location.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/macros.h" |
15 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
16 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
17 #include "base/synchronization/lock.h" | 18 #include "base/synchronization/lock.h" |
18 #include "base/win/windows_version.h" | 19 #include "base/win/windows_version.h" |
19 #include "mojo/embedder/platform_handle.h" | 20 #include "mojo/embedder/platform_handle.h" |
20 | 21 |
21 namespace mojo { | 22 namespace mojo { |
22 namespace system { | 23 namespace system { |
23 | 24 |
24 namespace { | 25 namespace { |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 scoped_ptr<WriteBuffer> write_buffer); | 118 scoped_ptr<WriteBuffer> write_buffer); |
118 | 119 |
119 private: | 120 private: |
120 virtual ~RawChannelIOHandler(); | 121 virtual ~RawChannelIOHandler(); |
121 | 122 |
122 // Returns true if |owner_| has been reset and there is not pending read or | 123 // Returns true if |owner_| has been reset and there is not pending read or |
123 // write. | 124 // write. |
124 // Must be called on the I/O thread. | 125 // Must be called on the I/O thread. |
125 bool ShouldSelfDestruct() const; | 126 bool ShouldSelfDestruct() const; |
126 | 127 |
127 // Must be called on the I/O thread. It could be called before or after | 128 // Must be called on the I/O thread. It may be called before or after |
128 // detached from the owner. | 129 // detaching from the owner. |
129 void OnReadCompleted(DWORD bytes_read, DWORD error); | 130 void OnReadCompleted(DWORD bytes_read, DWORD error); |
130 // Must be called on the I/O thread. It could be called before or after | 131 // Must be called on the I/O thread. It may be called before or after |
131 // detached from the owner. | 132 // detaching from the owner. |
132 void OnWriteCompleted(DWORD bytes_written, DWORD error); | 133 void OnWriteCompleted(DWORD bytes_written, DWORD error); |
133 | 134 |
134 embedder::ScopedPlatformHandle handle_; | 135 embedder::ScopedPlatformHandle handle_; |
135 | 136 |
136 // |owner_| is reset on the I/O thread under |owner_->write_lock()|. | 137 // |owner_| is reset on the I/O thread under |owner_->write_lock()|. |
137 // Therefore, it may be used on any thread under lock; or on the I/O thread | 138 // Therefore, it may be used on any thread under lock; or on the I/O thread |
138 // without locking. | 139 // without locking. |
139 RawChannelWin* owner_; | 140 RawChannelWin* owner_; |
140 | 141 |
141 // The following members must be used on the I/O thread. | 142 // The following members must be used on the I/O thread. |
142 scoped_ptr<ReadBuffer> preserved_read_buffer_after_detach_; | 143 scoped_ptr<ReadBuffer> preserved_read_buffer_after_detach_; |
143 scoped_ptr<WriteBuffer> preserved_write_buffer_after_detach_; | 144 scoped_ptr<WriteBuffer> preserved_write_buffer_after_detach_; |
| 145 bool suppress_self_destruct_; |
144 | 146 |
145 bool pending_read_; | 147 bool pending_read_; |
146 base::MessageLoopForIO::IOContext read_context_; | 148 base::MessageLoopForIO::IOContext read_context_; |
147 | 149 |
148 // The following members must be used under |owner_->write_lock()| while the | 150 // The following members must be used under |owner_->write_lock()| while the |
149 // object is still attached to the owner, and only on the I/O thread | 151 // object is still attached to the owner, and only on the I/O thread |
150 // afterwards. | 152 // afterwards. |
151 bool pending_write_; | 153 bool pending_write_; |
152 base::MessageLoopForIO::IOContext write_context_; | 154 base::MessageLoopForIO::IOContext write_context_; |
153 | 155 |
(...skipping 17 matching lines...) Expand all Loading... |
171 | 173 |
172 const bool skip_completion_port_on_success_; | 174 const bool skip_completion_port_on_success_; |
173 | 175 |
174 DISALLOW_COPY_AND_ASSIGN(RawChannelWin); | 176 DISALLOW_COPY_AND_ASSIGN(RawChannelWin); |
175 }; | 177 }; |
176 | 178 |
177 RawChannelWin::RawChannelIOHandler::RawChannelIOHandler( | 179 RawChannelWin::RawChannelIOHandler::RawChannelIOHandler( |
178 RawChannelWin* owner, | 180 RawChannelWin* owner, |
179 embedder::ScopedPlatformHandle handle) : handle_(handle.Pass()), | 181 embedder::ScopedPlatformHandle handle) : handle_(handle.Pass()), |
180 owner_(owner), | 182 owner_(owner), |
| 183 suppress_self_destruct_(false), |
181 pending_read_(false), | 184 pending_read_(false), |
182 pending_write_(false) { | 185 pending_write_(false) { |
183 memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped)); | 186 memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped)); |
184 read_context_.handler = this; | 187 read_context_.handler = this; |
185 memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped)); | 188 memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped)); |
186 write_context_.handler = this; | 189 write_context_.handler = this; |
187 | 190 |
188 owner_->message_loop_for_io()->RegisterIOHandler(handle_.get().handle, this); | 191 owner_->message_loop_for_io()->RegisterIOHandler(handle_.get().handle, this); |
189 } | 192 } |
190 | 193 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 pending_write_ = true; | 235 pending_write_ = true; |
233 } | 236 } |
234 | 237 |
235 void RawChannelWin::RawChannelIOHandler::OnIOCompleted( | 238 void RawChannelWin::RawChannelIOHandler::OnIOCompleted( |
236 base::MessageLoopForIO::IOContext* context, | 239 base::MessageLoopForIO::IOContext* context, |
237 DWORD bytes_transferred, | 240 DWORD bytes_transferred, |
238 DWORD error) { | 241 DWORD error) { |
239 DCHECK(!owner_ || | 242 DCHECK(!owner_ || |
240 base::MessageLoop::current() == owner_->message_loop_for_io()); | 243 base::MessageLoop::current() == owner_->message_loop_for_io()); |
241 | 244 |
242 if (context == &read_context_) | 245 { |
243 OnReadCompleted(bytes_transferred, error); | 246 // Suppress self-destruction inside |OnReadCompleted()|, etc. (in case they |
244 else if (context == &write_context_) | 247 // result in a call to |Shutdown()|). |
245 OnWriteCompleted(bytes_transferred, error); | 248 base::AutoReset<bool> resetter(&suppress_self_destruct_, true); |
246 else | 249 |
247 NOTREACHED(); | 250 if (context == &read_context_) |
| 251 OnReadCompleted(bytes_transferred, error); |
| 252 else if (context == &write_context_) |
| 253 OnWriteCompleted(bytes_transferred, error); |
| 254 else |
| 255 NOTREACHED(); |
| 256 } |
248 | 257 |
249 if (ShouldSelfDestruct()) | 258 if (ShouldSelfDestruct()) |
250 delete this; | 259 delete this; |
251 } | 260 } |
252 | 261 |
253 void RawChannelWin::RawChannelIOHandler::DetachFromOwnerNoLock( | 262 void RawChannelWin::RawChannelIOHandler::DetachFromOwnerNoLock( |
254 scoped_ptr<ReadBuffer> read_buffer, | 263 scoped_ptr<ReadBuffer> read_buffer, |
255 scoped_ptr<WriteBuffer> write_buffer) { | 264 scoped_ptr<WriteBuffer> write_buffer) { |
256 DCHECK(owner_); | 265 DCHECK(owner_); |
257 DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); | 266 DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); |
258 owner_->write_lock().AssertAcquired(); | 267 owner_->write_lock().AssertAcquired(); |
259 | 268 |
260 // If read/write is pending, we have to retain the corresponding buffer. | 269 // If read/write is pending, we have to retain the corresponding buffer. |
261 if (pending_read_) | 270 if (pending_read_) |
262 preserved_read_buffer_after_detach_ = read_buffer.Pass(); | 271 preserved_read_buffer_after_detach_ = read_buffer.Pass(); |
263 if (pending_write_) | 272 if (pending_write_) |
264 preserved_write_buffer_after_detach_ = write_buffer.Pass(); | 273 preserved_write_buffer_after_detach_ = write_buffer.Pass(); |
265 | 274 |
266 owner_ = NULL; | 275 owner_ = NULL; |
267 if (ShouldSelfDestruct()) | 276 if (ShouldSelfDestruct()) |
268 delete this; | 277 delete this; |
269 } | 278 } |
270 | 279 |
271 bool RawChannelWin::RawChannelIOHandler::ShouldSelfDestruct() const { | 280 bool RawChannelWin::RawChannelIOHandler::ShouldSelfDestruct() const { |
272 if (owner_) | 281 if (owner_ || suppress_self_destruct_) |
273 return false; | 282 return false; |
274 | 283 |
275 // Note: Detached, hence no lock needed for |pending_write_|. | 284 // Note: Detached, hence no lock needed for |pending_write_|. |
276 return !pending_read_ && !pending_write_; | 285 return !pending_read_ && !pending_write_; |
277 } | 286 } |
278 | 287 |
279 void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read, | 288 void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read, |
280 DWORD error) { | 289 DWORD error) { |
281 DCHECK(!owner_ || | 290 DCHECK(!owner_ || |
282 base::MessageLoop::current() == owner_->message_loop_for_io()); | 291 base::MessageLoop::current() == owner_->message_loop_for_io()); |
| 292 DCHECK(suppress_self_destruct_); |
283 | 293 |
284 CHECK(pending_read_); | 294 CHECK(pending_read_); |
285 pending_read_ = false; | 295 pending_read_ = false; |
286 if (!owner_) | 296 if (!owner_) |
287 return; | 297 return; |
288 | 298 |
289 if (error != ERROR_SUCCESS) { | 299 if (error != ERROR_SUCCESS) { |
290 DCHECK_EQ(bytes_read, 0u); | 300 DCHECK_EQ(bytes_read, 0u); |
291 PLOG_IF(ERROR, error != ERROR_BROKEN_PIPE) << "ReadFile"; | 301 PLOG_IF(ERROR, error != ERROR_BROKEN_PIPE) << "ReadFile"; |
292 owner_->OnReadCompleted(false, 0); | 302 owner_->OnReadCompleted(false, 0); |
293 } else { | 303 } else { |
294 DCHECK_GT(bytes_read, 0u); | 304 DCHECK_GT(bytes_read, 0u); |
295 owner_->OnReadCompleted(true, bytes_read); | 305 owner_->OnReadCompleted(true, bytes_read); |
296 } | 306 } |
297 } | 307 } |
298 | 308 |
299 void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written, | 309 void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written, |
300 DWORD error) { | 310 DWORD error) { |
301 DCHECK(!owner_ || | 311 DCHECK(!owner_ || |
302 base::MessageLoop::current() == owner_->message_loop_for_io()); | 312 base::MessageLoop::current() == owner_->message_loop_for_io()); |
| 313 DCHECK(suppress_self_destruct_); |
303 | 314 |
304 if (!owner_) { | 315 if (!owner_) { |
305 // No lock needed. | 316 // No lock needed. |
306 CHECK(pending_write_); | 317 CHECK(pending_write_); |
307 pending_write_ = false; | 318 pending_write_ = false; |
308 return; | 319 return; |
309 } | 320 } |
310 | 321 |
311 { | 322 { |
312 base::AutoLock locker(owner_->write_lock()); | 323 base::AutoLock locker(owner_->write_lock()); |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 | 527 |
517 // Static factory method declared in raw_channel.h. | 528 // Static factory method declared in raw_channel.h. |
518 // static | 529 // static |
519 scoped_ptr<RawChannel> RawChannel::Create( | 530 scoped_ptr<RawChannel> RawChannel::Create( |
520 embedder::ScopedPlatformHandle handle) { | 531 embedder::ScopedPlatformHandle handle) { |
521 return scoped_ptr<RawChannel>(new RawChannelWin(handle.Pass())); | 532 return scoped_ptr<RawChannel>(new RawChannelWin(handle.Pass())); |
522 } | 533 } |
523 | 534 |
524 } // namespace system | 535 } // namespace system |
525 } // namespace mojo | 536 } // namespace mojo |
OLD | NEW |