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

Side by Side Diff: mojo/system/raw_channel_win.cc

Issue 256503005: Mojo: Handle "nested" Shutdown() in RawChannelWin. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « mojo/system/raw_channel_unittest.cc ('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 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
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
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
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
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
OLDNEW
« no previous file with comments | « mojo/system/raw_channel_unittest.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698