OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ipc/ipc_channel_nacl.h" | 5 #include "ipc/ipc_channel_nacl.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <sys/types.h> | 9 #include <sys/types.h> |
10 | 10 |
11 #include <algorithm> | 11 #include <algorithm> |
12 | 12 |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/message_loop/message_loop_proxy.h" | 15 #include "base/single_thread_task_runner.h" |
16 #include "base/synchronization/lock.h" | 16 #include "base/synchronization/lock.h" |
17 #include "base/task_runner_util.h" | 17 #include "base/task_runner_util.h" |
| 18 #include "base/thread_task_runner_handle.h" |
18 #include "base/threading/simple_thread.h" | 19 #include "base/threading/simple_thread.h" |
19 #include "ipc/ipc_listener.h" | 20 #include "ipc/ipc_listener.h" |
20 #include "ipc/ipc_logging.h" | 21 #include "ipc/ipc_logging.h" |
21 #include "ipc/ipc_message_attachment_set.h" | 22 #include "ipc/ipc_message_attachment_set.h" |
22 #include "native_client/src/public/imc_syscalls.h" | 23 #include "native_client/src/public/imc_syscalls.h" |
23 #include "native_client/src/public/imc_types.h" | 24 #include "native_client/src/public/imc_types.h" |
24 | 25 |
25 namespace IPC { | 26 namespace IPC { |
26 | 27 |
27 struct MessageContents { | 28 struct MessageContents { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 public: | 68 public: |
68 // |pipe|: A file descriptor from which we will read using imc_recvmsg. | 69 // |pipe|: A file descriptor from which we will read using imc_recvmsg. |
69 // |data_read_callback|: A callback we invoke (on the main thread) when we | 70 // |data_read_callback|: A callback we invoke (on the main thread) when we |
70 // have read data. | 71 // have read data. |
71 // |failure_callback|: A callback we invoke when we have a failure reading | 72 // |failure_callback|: A callback we invoke when we have a failure reading |
72 // from |pipe|. | 73 // from |pipe|. |
73 // |main_message_loop|: A proxy for the main thread, where we will invoke the | 74 // |main_message_loop|: A proxy for the main thread, where we will invoke the |
74 // above callbacks. | 75 // above callbacks. |
75 ReaderThreadRunner( | 76 ReaderThreadRunner( |
76 int pipe, | 77 int pipe, |
77 base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback, | 78 base::Callback<void(scoped_ptr<MessageContents>)> data_read_callback, |
78 base::Callback<void ()> failure_callback, | 79 base::Callback<void()> failure_callback, |
79 scoped_refptr<base::MessageLoopProxy> main_message_loop); | 80 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner); |
80 | 81 |
81 // DelegateSimpleThread implementation. Reads data from the pipe in a loop | 82 // DelegateSimpleThread implementation. Reads data from the pipe in a loop |
82 // until either we are told to quit or a read fails. | 83 // until either we are told to quit or a read fails. |
83 void Run() override; | 84 void Run() override; |
84 | 85 |
85 private: | 86 private: |
86 int pipe_; | 87 int pipe_; |
87 base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback_; | 88 base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback_; |
88 base::Callback<void ()> failure_callback_; | 89 base::Callback<void ()> failure_callback_; |
89 scoped_refptr<base::MessageLoopProxy> main_message_loop_; | 90 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; |
90 | 91 |
91 DISALLOW_COPY_AND_ASSIGN(ReaderThreadRunner); | 92 DISALLOW_COPY_AND_ASSIGN(ReaderThreadRunner); |
92 }; | 93 }; |
93 | 94 |
94 ChannelNacl::ReaderThreadRunner::ReaderThreadRunner( | 95 ChannelNacl::ReaderThreadRunner::ReaderThreadRunner( |
95 int pipe, | 96 int pipe, |
96 base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback, | 97 base::Callback<void(scoped_ptr<MessageContents>)> data_read_callback, |
97 base::Callback<void ()> failure_callback, | 98 base::Callback<void()> failure_callback, |
98 scoped_refptr<base::MessageLoopProxy> main_message_loop) | 99 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner) |
99 : pipe_(pipe), | 100 : pipe_(pipe), |
100 data_read_callback_(data_read_callback), | 101 data_read_callback_(data_read_callback), |
101 failure_callback_(failure_callback), | 102 failure_callback_(failure_callback), |
102 main_message_loop_(main_message_loop) { | 103 main_task_runner_(main_task_runner) { |
103 } | 104 } |
104 | 105 |
105 void ChannelNacl::ReaderThreadRunner::Run() { | 106 void ChannelNacl::ReaderThreadRunner::Run() { |
106 while (true) { | 107 while (true) { |
107 scoped_ptr<MessageContents> msg_contents(new MessageContents); | 108 scoped_ptr<MessageContents> msg_contents(new MessageContents); |
108 bool success = ReadDataOnReaderThread(pipe_, msg_contents.get()); | 109 bool success = ReadDataOnReaderThread(pipe_, msg_contents.get()); |
109 if (success) { | 110 if (success) { |
110 main_message_loop_->PostTask(FROM_HERE, | 111 main_task_runner_->PostTask( |
| 112 FROM_HERE, |
111 base::Bind(data_read_callback_, base::Passed(&msg_contents))); | 113 base::Bind(data_read_callback_, base::Passed(&msg_contents))); |
112 } else { | 114 } else { |
113 main_message_loop_->PostTask(FROM_HERE, failure_callback_); | 115 main_task_runner_->PostTask(FROM_HERE, failure_callback_); |
114 // Because the read failed, we know we're going to quit. Don't bother | 116 // Because the read failed, we know we're going to quit. Don't bother |
115 // trying to read again. | 117 // trying to read again. |
116 return; | 118 return; |
117 } | 119 } |
118 } | 120 } |
119 } | 121 } |
120 | 122 |
121 ChannelNacl::ChannelNacl(const IPC::ChannelHandle& channel_handle, | 123 ChannelNacl::ChannelNacl(const IPC::ChannelHandle& channel_handle, |
122 Mode mode, | 124 Mode mode, |
123 Listener* listener) | 125 Listener* listener) |
(...skipping 28 matching lines...) Expand all Loading... |
152 bool ChannelNacl::Connect() { | 154 bool ChannelNacl::Connect() { |
153 if (pipe_ == -1) { | 155 if (pipe_ == -1) { |
154 DLOG(WARNING) << "Channel creation failed: " << pipe_name_; | 156 DLOG(WARNING) << "Channel creation failed: " << pipe_name_; |
155 return false; | 157 return false; |
156 } | 158 } |
157 | 159 |
158 // Note that Connect is called on the "Channel" thread (i.e., the same thread | 160 // Note that Connect is called on the "Channel" thread (i.e., the same thread |
159 // where Channel::Send will be called, and the same thread that should receive | 161 // where Channel::Send will be called, and the same thread that should receive |
160 // messages). The constructor might be invoked on another thread (see | 162 // messages). The constructor might be invoked on another thread (see |
161 // ChannelProxy for an example of that). Therefore, we must wait until Connect | 163 // ChannelProxy for an example of that). Therefore, we must wait until Connect |
162 // is called to decide which MessageLoopProxy to pass to ReaderThreadRunner. | 164 // is called to decide which SingleThreadTaskRunner to pass to |
163 reader_thread_runner_.reset( | 165 // ReaderThreadRunner. |
164 new ReaderThreadRunner( | 166 reader_thread_runner_.reset(new ReaderThreadRunner( |
165 pipe_, | 167 pipe_, |
166 base::Bind(&ChannelNacl::DidRecvMsg, | 168 base::Bind(&ChannelNacl::DidRecvMsg, weak_ptr_factory_.GetWeakPtr()), |
167 weak_ptr_factory_.GetWeakPtr()), | 169 base::Bind(&ChannelNacl::ReadDidFail, weak_ptr_factory_.GetWeakPtr()), |
168 base::Bind(&ChannelNacl::ReadDidFail, | 170 base::ThreadTaskRunnerHandle::Get())); |
169 weak_ptr_factory_.GetWeakPtr()), | |
170 base::MessageLoopProxy::current())); | |
171 reader_thread_.reset( | 171 reader_thread_.reset( |
172 new base::DelegateSimpleThread(reader_thread_runner_.get(), | 172 new base::DelegateSimpleThread(reader_thread_runner_.get(), |
173 "ipc_channel_nacl reader thread")); | 173 "ipc_channel_nacl reader thread")); |
174 reader_thread_->Start(); | 174 reader_thread_->Start(); |
175 waiting_connect_ = false; | 175 waiting_connect_ = false; |
176 // If there were any messages queued before connection, send them. | 176 // If there were any messages queued before connection, send them. |
177 ProcessOutgoingMessages(); | 177 ProcessOutgoingMessages(); |
178 base::MessageLoopProxy::current()->PostTask(FROM_HERE, | 178 base::ThreadTaskRunnerHandle::Get()->PostTask( |
179 base::Bind(&ChannelNacl::CallOnChannelConnected, | 179 FROM_HERE, base::Bind(&ChannelNacl::CallOnChannelConnected, |
180 weak_ptr_factory_.GetWeakPtr())); | 180 weak_ptr_factory_.GetWeakPtr())); |
181 | 181 |
182 return true; | 182 return true; |
183 } | 183 } |
184 | 184 |
185 void ChannelNacl::Close() { | 185 void ChannelNacl::Close() { |
186 // For now, we assume that at shutdown, the reader thread will be woken with | 186 // For now, we assume that at shutdown, the reader thread will be woken with |
187 // a failure (see NaClIPCAdapter::BlockingRead and CloseChannel). Or... we | 187 // a failure (see NaClIPCAdapter::BlockingRead and CloseChannel). Or... we |
188 // might simply be killed with no chance to clean up anyway :-). | 188 // might simply be killed with no chance to clean up anyway :-). |
189 // If untrusted code tries to close the channel prior to shutdown, it's likely | 189 // If untrusted code tries to close the channel prior to shutdown, it's likely |
190 // to hang. | 190 // to hang. |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 // Channel's methods | 372 // Channel's methods |
373 | 373 |
374 // static | 374 // static |
375 scoped_ptr<Channel> Channel::Create( | 375 scoped_ptr<Channel> Channel::Create( |
376 const IPC::ChannelHandle &channel_handle, Mode mode, Listener* listener) { | 376 const IPC::ChannelHandle &channel_handle, Mode mode, Listener* listener) { |
377 return scoped_ptr<Channel>( | 377 return scoped_ptr<Channel>( |
378 new ChannelNacl(channel_handle, mode, listener)); | 378 new ChannelNacl(channel_handle, mode, listener)); |
379 } | 379 } |
380 | 380 |
381 } // namespace IPC | 381 } // namespace IPC |
OLD | NEW |