blob: 11aab8d6155bf27aaf24bc0b1ac9f9775a19f1ff [file] [log] [blame]
[email protected]64860882014-08-04 23:44:171// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ipc/mojo/ipc_message_pipe_reader.h"
6
tfarina10a5c062015-09-04 18:47:577#include <stdint.h>
8
[email protected]64860882014-08-04 23:44:179#include "base/bind.h"
10#include "base/bind_helpers.h"
11#include "base/location.h"
12#include "base/logging.h"
skyostile687bdff2015-05-12 11:29:2113#include "base/single_thread_task_runner.h"
14#include "base/thread_task_runner_handle.h"
morritadcc28ab2015-01-10 01:49:2115#include "ipc/mojo/async_handle_waiter.h"
morritad68bedf42014-11-25 23:35:5716#include "ipc/mojo/ipc_channel_mojo.h"
[email protected]64860882014-08-04 23:44:1717
18namespace IPC {
19namespace internal {
20
morritad68bedf42014-11-25 23:35:5721MessagePipeReader::MessagePipeReader(mojo::ScopedMessagePipeHandle handle,
22 MessagePipeReader::Delegate* delegate)
morritadcc28ab2015-01-10 01:49:2123 : pipe_(handle.Pass()),
amistry0b0e7482015-09-02 18:04:2224 handle_copy_(pipe_.get().value()),
morritadcc28ab2015-01-10 01:49:2125 delegate_(delegate),
26 async_waiter_(
27 new AsyncHandleWaiter(base::Bind(&MessagePipeReader::PipeIsReady,
morritab4472142015-04-20 21:20:1228 base::Unretained(this)))),
29 pending_send_error_(MOJO_RESULT_OK) {
[email protected]64860882014-08-04 23:44:1730}
31
32MessagePipeReader::~MessagePipeReader() {
amistry0b0e7482015-09-02 18:04:2233 DCHECK(thread_checker_.CalledOnValidThread());
morritab4472142015-04-20 21:20:1234 // The pipe should be closed before deletion.
[email protected]64860882014-08-04 23:44:1735 CHECK(!IsValid());
36}
37
38void MessagePipeReader::Close() {
amistry0b0e7482015-09-02 18:04:2239 DCHECK(thread_checker_.CalledOnValidThread());
morritadcc28ab2015-01-10 01:49:2140 async_waiter_.reset();
[email protected]64860882014-08-04 23:44:1741 pipe_.reset();
42 OnPipeClosed();
43}
44
45void MessagePipeReader::CloseWithError(MojoResult error) {
amistry0b0e7482015-09-02 18:04:2246 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]64860882014-08-04 23:44:1747 OnPipeError(error);
48 Close();
49}
50
morritab4472142015-04-20 21:20:1251void MessagePipeReader::CloseWithErrorIfPending() {
amistry0b0e7482015-09-02 18:04:2252 DCHECK(thread_checker_.CalledOnValidThread());
53 MojoResult pending_error = base::subtle::NoBarrier_Load(&pending_send_error_);
54 if (pending_error == MOJO_RESULT_OK)
morritab4472142015-04-20 21:20:1255 return;
amistry0b0e7482015-09-02 18:04:2256 // NOTE: This races with Send(), and therefore the value of
57 // pending_send_error() can change.
58 CloseWithError(pending_error);
morritab4472142015-04-20 21:20:1259 return;
60}
61
62void MessagePipeReader::CloseWithErrorLater(MojoResult error) {
amistry0b0e7482015-09-02 18:04:2263 DCHECK_NE(error, MOJO_RESULT_OK);
64 // NOTE: No assumptions about the value of |pending_send_error_| or whether or
65 // not the error has been signaled can be made. If Send() is called
66 // immediately before Close() and errors, it's possible for the error to not
67 // be signaled.
68 base::subtle::NoBarrier_Store(&pending_send_error_, error);
morritab4472142015-04-20 21:20:1269}
70
morritad68bedf42014-11-25 23:35:5771bool MessagePipeReader::Send(scoped_ptr<Message> message) {
yuhaoz9b8157d2015-08-18 22:21:3572 TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
73 "MessagePipeReader::Send",
74 message->flags(),
75 TRACE_EVENT_FLAG_FLOW_OUT);
morritad68bedf42014-11-25 23:35:5776 std::vector<MojoHandle> handles;
77 MojoResult result = MOJO_RESULT_OK;
morrita4b5c28e22015-01-14 21:17:0678 result = ChannelMojo::ReadFromMessageAttachmentSet(message.get(), &handles);
morritad68bedf42014-11-25 23:35:5779 if (result == MOJO_RESULT_OK) {
80 result = MojoWriteMessage(handle(),
81 message->data(),
tfarina10a5c062015-09-04 18:47:5782 static_cast<uint32_t>(message->size()),
morritad68bedf42014-11-25 23:35:5783 handles.empty() ? nullptr : &handles[0],
tfarina10a5c062015-09-04 18:47:5784 static_cast<uint32_t>(handles.size()),
morritad68bedf42014-11-25 23:35:5785 MOJO_WRITE_MESSAGE_FLAG_NONE);
86 }
87
88 if (result != MOJO_RESULT_OK) {
89 std::for_each(handles.begin(), handles.end(), &MojoClose);
morritab4472142015-04-20 21:20:1290 // We cannot call CloseWithError() here as Send() is protected by
91 // ChannelMojo's lock and CloseWithError() could re-enter ChannelMojo. We
92 // cannot call CloseWithError() also because Send() can be called from
93 // non-UI thread while OnPipeError() expects to be called on IO thread.
94 CloseWithErrorLater(result);
morritad68bedf42014-11-25 23:35:5795 return false;
96 }
97
98 return true;
99}
100
morritad68bedf42014-11-25 23:35:57101void MessagePipeReader::OnMessageReceived() {
102 Message message(data_buffer().empty() ? "" : &data_buffer()[0],
tfarina10a5c062015-09-04 18:47:57103 static_cast<uint32_t>(data_buffer().size()));
morritad68bedf42014-11-25 23:35:57104
105 std::vector<MojoHandle> handle_buffer;
106 TakeHandleBuffer(&handle_buffer);
morritad68bedf42014-11-25 23:35:57107 MojoResult write_result =
morrita4b5c28e22015-01-14 21:17:06108 ChannelMojo::WriteToMessageAttachmentSet(handle_buffer, &message);
morritad68bedf42014-11-25 23:35:57109 if (write_result != MOJO_RESULT_OK) {
110 CloseWithError(write_result);
111 return;
112 }
morritad68bedf42014-11-25 23:35:57113
yuhaoz9b8157d2015-08-18 22:21:35114 TRACE_EVENT_WITH_FLOW0(TRACE_DISABLED_BY_DEFAULT("ipc.flow"),
115 "MessagePipeReader::OnMessageReceived",
116 message.flags(),
117 TRACE_EVENT_FLAG_FLOW_IN);
morritad68bedf42014-11-25 23:35:57118 delegate_->OnMessageReceived(message);
[email protected]64860882014-08-04 23:44:17119}
120
morritad68bedf42014-11-25 23:35:57121void MessagePipeReader::OnPipeClosed() {
amistry0b0e7482015-09-02 18:04:22122 DCHECK(thread_checker_.CalledOnValidThread());
morritad68bedf42014-11-25 23:35:57123 if (!delegate_)
[email protected]64860882014-08-04 23:44:17124 return;
morritad68bedf42014-11-25 23:35:57125 delegate_->OnPipeClosed(this);
126 delegate_ = nullptr;
127}
128
129void MessagePipeReader::OnPipeError(MojoResult error) {
amistry0b0e7482015-09-02 18:04:22130 DCHECK(thread_checker_.CalledOnValidThread());
morritad68bedf42014-11-25 23:35:57131 if (!delegate_)
132 return;
133 delegate_->OnPipeError(this);
134}
135
136MojoResult MessagePipeReader::ReadMessageBytes() {
amistry0b0e7482015-09-02 18:04:22137 DCHECK(thread_checker_.CalledOnValidThread());
morritad68bedf42014-11-25 23:35:57138 DCHECK(handle_buffer_.empty());
139
140 uint32_t num_bytes = static_cast<uint32_t>(data_buffer_.size());
141 uint32_t num_handles = 0;
142 MojoResult result = MojoReadMessage(pipe_.get().value(),
143 num_bytes ? &data_buffer_[0] : nullptr,
144 &num_bytes,
145 nullptr,
146 &num_handles,
147 MOJO_READ_MESSAGE_FLAG_NONE);
148 data_buffer_.resize(num_bytes);
149 handle_buffer_.resize(num_handles);
150 if (result == MOJO_RESULT_RESOURCE_EXHAUSTED) {
151 // MOJO_RESULT_RESOURCE_EXHAUSTED was asking the caller that
152 // it needs more bufer. So we re-read it with resized buffers.
153 result = MojoReadMessage(pipe_.get().value(),
154 num_bytes ? &data_buffer_[0] : nullptr,
155 &num_bytes,
156 num_handles ? &handle_buffer_[0] : nullptr,
157 &num_handles,
158 MOJO_READ_MESSAGE_FLAG_NONE);
159 }
160
161 DCHECK(0 == num_bytes || data_buffer_.size() == num_bytes);
162 DCHECK(0 == num_handles || handle_buffer_.size() == num_handles);
163 return result;
[email protected]64860882014-08-04 23:44:17164}
165
morritadcc28ab2015-01-10 01:49:21166void MessagePipeReader::ReadAvailableMessages() {
amistry0b0e7482015-09-02 18:04:22167 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]64860882014-08-04 23:44:17168 while (pipe_.is_valid()) {
169 MojoResult read_result = ReadMessageBytes();
170 if (read_result == MOJO_RESULT_SHOULD_WAIT)
171 break;
172 if (read_result != MOJO_RESULT_OK) {
morrita0b35325d2015-06-11 18:38:57173 DLOG(WARNING)
174 << "Pipe got error from ReadMessage(). Closing: " << read_result;
175 OnPipeError(read_result);
[email protected]64860882014-08-04 23:44:17176 Close();
177 break;
178 }
179
180 OnMessageReceived();
181 }
182
[email protected]64860882014-08-04 23:44:17183}
184
morritadcc28ab2015-01-10 01:49:21185void MessagePipeReader::ReadMessagesThenWait() {
amistry0b0e7482015-09-02 18:04:22186 DCHECK(thread_checker_.CalledOnValidThread());
morritadcc28ab2015-01-10 01:49:21187 while (true) {
188 ReadAvailableMessages();
189 if (!pipe_.is_valid())
190 break;
191 // |Wait()| is safe to call only after all messages are read.
192 // If can fail with |MOJO_RESULT_ALREADY_EXISTS| otherwise.
193 // Also, we don't use MOJO_HANDLE_SIGNAL_WRITABLE here, expecting buffer in
194 // MessagePipe.
tkent5eab51f2015-03-25 04:40:10195 MojoResult result =
196 async_waiter_->Wait(pipe_.get().value(), MOJO_HANDLE_SIGNAL_READABLE);
morritadcc28ab2015-01-10 01:49:21197 // If the result is |MOJO_RESULT_ALREADY_EXISTS|, there could be messages
198 // that have been arrived after the last |ReadAvailableMessages()|.
199 // We have to consume then and retry in that case.
200 if (result != MOJO_RESULT_ALREADY_EXISTS) {
201 if (result != MOJO_RESULT_OK) {
morritaa3889aa2015-03-16 22:40:51202 LOG(ERROR) << "Failed to wait on the pipe. Result is " << result;
morritadcc28ab2015-01-10 01:49:21203 OnPipeError(result);
204 Close();
205 }
206
207 break;
208 }
209 }
morritad68bedf42014-11-25 23:35:57210}
[email protected]64860882014-08-04 23:44:17211
morritadcc28ab2015-01-10 01:49:21212void MessagePipeReader::PipeIsReady(MojoResult wait_result) {
amistry0b0e7482015-09-02 18:04:22213 DCHECK(thread_checker_.CalledOnValidThread());
morritab4472142015-04-20 21:20:12214 CloseWithErrorIfPending();
215 if (!IsValid()) {
216 // There was a pending error and it closed the pipe.
217 // We cannot do the work anymore.
218 return;
219 }
220
morritadcc28ab2015-01-10 01:49:21221 if (wait_result != MOJO_RESULT_OK) {
tkent5eab51f2015-03-25 04:40:10222 if (wait_result != MOJO_RESULT_ABORTED) {
223 // FAILED_PRECONDITION happens every time the peer is dead so
224 // it isn't worth polluting the log message.
225 LOG_IF(WARNING, wait_result != MOJO_RESULT_FAILED_PRECONDITION)
226 << "Pipe got error from the waiter. Closing: " << wait_result;
227 OnPipeError(wait_result);
228 }
morritadcc28ab2015-01-10 01:49:21229
230 Close();
morritad68bedf42014-11-25 23:35:57231 return;
morritadcc28ab2015-01-10 01:49:21232 }
233
234 ReadMessagesThenWait();
[email protected]64860882014-08-04 23:44:17235}
236
237void MessagePipeReader::DelayedDeleter::operator()(
238 MessagePipeReader* ptr) const {
239 ptr->Close();
skyostile687bdff2015-05-12 11:29:21240 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
241 base::Bind(&DeleteNow, ptr));
[email protected]64860882014-08-04 23:44:17242}
243
244} // namespace internal
245} // namespace IPC