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

Side by Side Diff: chrome/common/ipc_channel_win.cc

Issue 19617: Add thread checks to the IPC channel.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 "chrome/common/ipc_channel_win.h" 5 #include "chrome/common/ipc_channel_win.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <sstream> 8 #include <sstream>
9 9
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/non_thread_safe.h"
12 #include "base/win_util.h" 13 #include "base/win_util.h"
13 #include "chrome/common/chrome_counters.h" 14 #include "chrome/common/chrome_counters.h"
14 #include "chrome/common/ipc_logging.h" 15 #include "chrome/common/ipc_logging.h"
15 #include "chrome/common/ipc_message_utils.h" 16 #include "chrome/common/ipc_message_utils.h"
16 17
17 namespace IPC { 18 namespace IPC {
18 //------------------------------------------------------------------------------ 19 //------------------------------------------------------------------------------
19 20
20 Channel::ChannelImpl::State::State(ChannelImpl* channel) : is_pending(false) { 21 Channel::ChannelImpl::State::State(ChannelImpl* channel) : is_pending(false) {
21 memset(&context.overlapped, 0, sizeof(context.overlapped)); 22 memset(&context.overlapped, 0, sizeof(context.overlapped));
(...skipping 17 matching lines...) Expand all
39 processing_incoming_(false), 40 processing_incoming_(false),
40 ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) { 41 ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
41 if (!CreatePipe(channel_id, mode)) { 42 if (!CreatePipe(channel_id, mode)) {
42 // The pipe may have been closed already. 43 // The pipe may have been closed already.
43 LOG(WARNING) << "Unable to create pipe named \"" << channel_id << 44 LOG(WARNING) << "Unable to create pipe named \"" << channel_id <<
44 "\" in " << (mode == 0 ? "server" : "client") << " mode."; 45 "\" in " << (mode == 0 ? "server" : "client") << " mode.";
45 } 46 }
46 } 47 }
47 48
48 void Channel::ChannelImpl::Close() { 49 void Channel::ChannelImpl::Close() {
50 if (thread_check_.get()) {
51 DCHECK(thread_check_->CalledOnValidThread());
52 }
53
49 bool waited = false; 54 bool waited = false;
50 if (input_state_.is_pending || output_state_.is_pending) { 55 if (input_state_.is_pending || output_state_.is_pending) {
51 CancelIo(pipe_); 56 CancelIo(pipe_);
52 waited = true; 57 waited = true;
53 } 58 }
54 59
55 // Closing the handle at this point prevents us from issuing more requests 60 // Closing the handle at this point prevents us from issuing more requests
56 // form OnIOCompleted(). 61 // form OnIOCompleted().
57 if (pipe_ != INVALID_HANDLE_VALUE) { 62 if (pipe_ != INVALID_HANDLE_VALUE) {
58 CloseHandle(pipe_); 63 CloseHandle(pipe_);
(...skipping 11 matching lines...) Expand all
70 } 75 }
71 76
72 while (!output_queue_.empty()) { 77 while (!output_queue_.empty()) {
73 Message* m = output_queue_.front(); 78 Message* m = output_queue_.front();
74 output_queue_.pop(); 79 output_queue_.pop();
75 delete m; 80 delete m;
76 } 81 }
77 } 82 }
78 83
79 bool Channel::ChannelImpl::Send(Message* message) { 84 bool Channel::ChannelImpl::Send(Message* message) {
85 DCHECK(thread_check_->CalledOnValidThread());
80 chrome::Counters::ipc_send_counter().Increment(); 86 chrome::Counters::ipc_send_counter().Increment();
81 #ifdef IPC_MESSAGE_DEBUG_EXTRA 87 #ifdef IPC_MESSAGE_DEBUG_EXTRA
82 DLOG(INFO) << "sending message @" << message << " on channel @" << this 88 DLOG(INFO) << "sending message @" << message << " on channel @" << this
83 << " with type " << message->type() 89 << " with type " << message->type()
84 << " (" << output_queue_.size() << " in queue)"; 90 << " (" << output_queue_.size() << " in queue)";
85 #endif 91 #endif
86 92
87 #ifdef IPC_MESSAGE_LOG_ENABLED 93 #ifdef IPC_MESSAGE_LOG_ENABLED
88 Logging::current()->OnSendMessage(message, L""); 94 Logging::current()->OnSendMessage(message, L"");
89 #endif 95 #endif
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 return false; 166 return false;
161 } 167 }
162 168
163 output_queue_.push(m.release()); 169 output_queue_.push(m.release());
164 return true; 170 return true;
165 } 171 }
166 172
167 bool Channel::ChannelImpl::Connect() { 173 bool Channel::ChannelImpl::Connect() {
168 DLOG(WARNING) << "Connect called twice"; 174 DLOG(WARNING) << "Connect called twice";
169 175
176 if (!thread_check_.get())
jam 2009/01/28 03:33:58 since this is only used in debug builds, it should
177 thread_check_.reset(new NonThreadSafe());
178
170 if (pipe_ == INVALID_HANDLE_VALUE) 179 if (pipe_ == INVALID_HANDLE_VALUE)
171 return false; 180 return false;
172 181
173 MessageLoopForIO::current()->RegisterIOHandler(pipe_, this); 182 MessageLoopForIO::current()->RegisterIOHandler(pipe_, this);
174 183
175 // Check to see if there is a client connected to our pipe... 184 // Check to see if there is a client connected to our pipe...
176 if (waiting_connect_) 185 if (waiting_connect_)
177 ProcessConnection(); 186 ProcessConnection();
178 187
179 if (!input_state_.is_pending) { 188 if (!input_state_.is_pending) {
180 // Complete setup asynchronously. By not setting input_state_.is_pending 189 // Complete setup asynchronously. By not setting input_state_.is_pending
181 // to true, we indicate to OnIOCompleted that this is the special 190 // to true, we indicate to OnIOCompleted that this is the special
182 // initialization signal. 191 // initialization signal.
183 MessageLoopForIO::current()->PostTask(FROM_HERE, factory_.NewRunnableMethod( 192 MessageLoopForIO::current()->PostTask(FROM_HERE, factory_.NewRunnableMethod(
184 &Channel::ChannelImpl::OnIOCompleted, &input_state_.context, 0, 0)); 193 &Channel::ChannelImpl::OnIOCompleted, &input_state_.context, 0, 0));
185 } 194 }
186 195
187 if (!waiting_connect_) 196 if (!waiting_connect_)
188 ProcessOutgoingMessages(NULL, 0); 197 ProcessOutgoingMessages(NULL, 0);
189 return true; 198 return true;
190 } 199 }
191 200
192 bool Channel::ChannelImpl::ProcessConnection() { 201 bool Channel::ChannelImpl::ProcessConnection() {
202 DCHECK(thread_check_->CalledOnValidThread());
193 if (input_state_.is_pending) 203 if (input_state_.is_pending)
194 input_state_.is_pending = false; 204 input_state_.is_pending = false;
195 205
196 // Do we have a client connected to our pipe? 206 // Do we have a client connected to our pipe?
197 if (INVALID_HANDLE_VALUE == pipe_) 207 if (INVALID_HANDLE_VALUE == pipe_)
198 return false; 208 return false;
199 209
200 BOOL ok = ConnectNamedPipe(pipe_, &input_state_.context.overlapped); 210 BOOL ok = ConnectNamedPipe(pipe_, &input_state_.context.overlapped);
201 211
202 DWORD err = GetLastError(); 212 DWORD err = GetLastError();
(...skipping 15 matching lines...) Expand all
218 NOTREACHED(); 228 NOTREACHED();
219 return false; 229 return false;
220 } 230 }
221 231
222 return true; 232 return true;
223 } 233 }
224 234
225 bool Channel::ChannelImpl::ProcessIncomingMessages( 235 bool Channel::ChannelImpl::ProcessIncomingMessages(
226 MessageLoopForIO::IOContext* context, 236 MessageLoopForIO::IOContext* context,
227 DWORD bytes_read) { 237 DWORD bytes_read) {
238 DCHECK(thread_check_->CalledOnValidThread());
228 if (input_state_.is_pending) { 239 if (input_state_.is_pending) {
229 input_state_.is_pending = false; 240 input_state_.is_pending = false;
230 DCHECK(context); 241 DCHECK(context);
231 242
232 if (!context || !bytes_read) 243 if (!context || !bytes_read)
233 return false; 244 return false;
234 } else { 245 } else {
235 // This happens at channel initialization. 246 // This happens at channel initialization.
236 DCHECK(!bytes_read && context == &input_state_.context); 247 DCHECK(!bytes_read && context == &input_state_.context);
237 } 248 }
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 } 317 }
307 318
308 return true; 319 return true;
309 } 320 }
310 321
311 bool Channel::ChannelImpl::ProcessOutgoingMessages( 322 bool Channel::ChannelImpl::ProcessOutgoingMessages(
312 MessageLoopForIO::IOContext* context, 323 MessageLoopForIO::IOContext* context,
313 DWORD bytes_written) { 324 DWORD bytes_written) {
314 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's 325 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
315 // no connection? 326 // no connection?
327 DCHECK(thread_check_->CalledOnValidThread());
316 328
317 if (output_state_.is_pending) { 329 if (output_state_.is_pending) {
318 DCHECK(context); 330 DCHECK(context);
319 output_state_.is_pending = false; 331 output_state_.is_pending = false;
320 if (!context || bytes_written == 0) { 332 if (!context || bytes_written == 0) {
321 DWORD err = GetLastError(); 333 DWORD err = GetLastError();
322 LOG(ERROR) << "pipe error: " << err; 334 LOG(ERROR) << "pipe error: " << err;
323 return false; 335 return false;
324 } 336 }
325 // Message was sent. 337 // Message was sent.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 " with type " << m->type(); 375 " with type " << m->type();
364 #endif 376 #endif
365 377
366 output_state_.is_pending = true; 378 output_state_.is_pending = true;
367 return true; 379 return true;
368 } 380 }
369 381
370 void Channel::ChannelImpl::OnIOCompleted(MessageLoopForIO::IOContext* context, 382 void Channel::ChannelImpl::OnIOCompleted(MessageLoopForIO::IOContext* context,
371 DWORD bytes_transfered, DWORD error) { 383 DWORD bytes_transfered, DWORD error) {
372 bool ok; 384 bool ok;
385 DCHECK(thread_check_->CalledOnValidThread());
373 if (context == &input_state_.context) { 386 if (context == &input_state_.context) {
374 if (waiting_connect_) { 387 if (waiting_connect_) {
375 if (!ProcessConnection()) 388 if (!ProcessConnection())
376 return; 389 return;
377 // We may have some messages queued up to send... 390 // We may have some messages queued up to send...
378 if (!output_queue_.empty() && !output_state_.is_pending) 391 if (!output_queue_.empty() && !output_state_.is_pending)
379 ProcessOutgoingMessages(NULL, 0); 392 ProcessOutgoingMessages(NULL, 0);
380 if (input_state_.is_pending) 393 if (input_state_.is_pending)
381 return; 394 return;
382 // else, fall-through and look for incoming messages... 395 // else, fall-through and look for incoming messages...
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 431
419 void Channel::set_listener(Listener* listener) { 432 void Channel::set_listener(Listener* listener) {
420 channel_impl_->set_listener(listener); 433 channel_impl_->set_listener(listener);
421 } 434 }
422 435
423 bool Channel::Send(Message* message) { 436 bool Channel::Send(Message* message) {
424 return channel_impl_->Send(message); 437 return channel_impl_->Send(message);
425 } 438 }
426 439
427 } // namespace IPC 440 } // namespace IPC
OLDNEW
« chrome/common/ipc_channel_win.h ('K') | « chrome/common/ipc_channel_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698