Index: mojo/edk/system/channel_win.cc |
diff --git a/mojo/edk/system/channel_win.cc b/mojo/edk/system/channel_win.cc |
index 77a19a68ff75d6ece43d2c182982ae90b386da80..f05c55de3500e34794384be498bae907a9c40dbb 100644 |
--- a/mojo/edk/system/channel_win.cc |
+++ b/mojo/edk/system/channel_win.cc |
@@ -77,6 +77,9 @@ class ChannelWin : public Channel, |
self_(this), |
handle_(std::move(handle)), |
io_task_runner_(io_task_runner) { |
+ memset(&connect_context_, 0, sizeof(connect_context_)); |
+ connect_context_.handler = this; |
+ |
memset(&read_context_, 0, sizeof(read_context_)); |
read_context_.handler = this; |
@@ -141,7 +144,27 @@ class ChannelWin : public Channel, |
base::MessageLoopForIO::current()->RegisterIOHandler( |
handle_.get().handle, this); |
- // Now that we have registered our IOHandler, we can start writing. |
+ // We may be starting the channel with a disconnected server pipe, e.g., |
+ // when not using PlatformChannelPair. Make sure the pipe is connected |
+ // before we attempt to do any reading or writing. |
+ BOOL result = ConnectNamedPipe(handle_.get().handle, |
+ &connect_context_.overlapped); |
+ if (!result && (GetLastError() == ERROR_PIPE_CONNECTED || |
+ GetLastError() == ERROR_INVALID_FUNCTION)) { |
+ // If the pipe's already connected, we can start using it immediately. |
+ // Note that ERROR_INVALID_FUNCTION is returned if we call this on a |
+ // client pipe. If this is a client pipe we know it's already connected. |
+ OnPipeConnected(); |
+ } else if (result || GetLastError() == ERROR_IO_PENDING) { |
+ // Balanced in OnIOCompleted. |
+ AddRef(); |
+ } else { |
+ OnError(); |
+ } |
+ } |
+ |
+ void OnPipeConnected() { |
+ // Now that we are connected we can start writing and reading. |
{ |
base::AutoLock lock(write_lock_); |
if (delay_writes_) { |
@@ -180,9 +203,11 @@ class ChannelWin : public Channel, |
OnError(); |
} else if (context == &read_context_) { |
OnReadDone(static_cast<size_t>(bytes_transfered)); |
- } else { |
- CHECK(context == &write_context_); |
+ } else if (context == &write_context_) { |
OnWriteDone(static_cast<size_t>(bytes_transfered)); |
+ } else { |
+ CHECK(context == &connect_context_); |
+ OnPipeConnected(); |
} |
Release(); // Balancing reference taken after ReadFile / WriteFile. |
} |
@@ -276,6 +301,7 @@ class ChannelWin : public Channel, |
ScopedPlatformHandle handle_; |
scoped_refptr<base::TaskRunner> io_task_runner_; |
+ base::MessageLoopForIO::IOContext connect_context_; |
base::MessageLoopForIO::IOContext read_context_; |
base::MessageLoopForIO::IOContext write_context_; |