blob: f5134a5110b1dbf53b88fb0e73f6e7b61fe88785 [file] [log] [blame]
[email protected]522cc10d2012-01-11 22:39:541// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]22b42c52010-12-20 06:59:235#include "ipc/ipc_sync_channel.h"
6
avi246998d82015-12-22 02:39:047#include <stddef.h>
8
danakj03de39b22016-04-23 04:21:099#include <memory>
initial.commit09911bf2008-07-26 23:55:2910#include <string>
sammc4bcc4ed62016-10-27 10:13:5911#include <utility>
initial.commit09911bf2008-07-26 23:55:2912#include <vector>
13
[email protected]72b6f8e22011-11-12 21:16:4114#include "base/bind.h"
skyostile687bdff2015-05-12 11:29:2115#include "base/location.h"
initial.commit09911bf2008-07-26 23:55:2916#include "base/logging.h"
tfarina4da82752015-09-16 09:56:2117#include "base/macros.h"
Alexander Timin4f9c35c2018-11-01 20:15:2018#include "base/message_loop/message_loop.h"
[email protected]e66ef602013-07-24 05:15:2419#include "base/process/process_handle.h"
[email protected]2d6e6a72013-02-08 20:11:0220#include "base/run_loop.h"
skyostile687bdff2015-05-12 11:29:2121#include "base/single_thread_task_runner.h"
[email protected]4aa794a12013-06-11 06:32:1822#include "base/strings/string_util.h"
23#include "base/synchronization/waitable_event.h"
[email protected]f214f8792011-01-01 02:17:0824#include "base/threading/platform_thread.h"
[email protected]34b99632011-01-01 01:01:0625#include "base/threading/thread.h"
gabf08ccc02016-05-11 18:51:1126#include "base/threading/thread_task_runner_handle.h"
avi246998d82015-12-22 02:39:0427#include "build/build_config.h"
[email protected]57319ce2012-06-11 22:35:2628#include "ipc/ipc_listener.h"
[email protected]946d1b22009-07-22 23:57:2129#include "ipc/ipc_message.h"
[email protected]57319ce2012-06-11 22:35:2630#include "ipc/ipc_sender.h"
[email protected]1e9499c2010-04-06 20:33:3631#include "ipc/ipc_sync_message_filter.h"
[email protected]21fa3a12010-12-08 23:34:1632#include "ipc/ipc_sync_message_unittest.h"
sammc4bcc4ed62016-10-27 10:13:5933#include "mojo/public/cpp/system/message_pipe.h"
initial.commit09911bf2008-07-26 23:55:2934#include "testing/gtest/include/gtest/gtest.h"
35
[email protected]aa96ae772009-01-20 22:08:1536using base::WaitableEvent;
[email protected]c9e0c7332011-05-13 22:42:4137
[email protected]2d6e6a72013-02-08 20:11:0238namespace IPC {
[email protected]dd3eac22008-08-26 07:28:3439namespace {
40
initial.commit09911bf2008-07-26 23:55:2941// Base class for a "process" with listener and IPC threads.
[email protected]57319ce2012-06-11 22:35:2642class Worker : public Listener, public Sender {
initial.commit09911bf2008-07-26 23:55:2943 public:
44 // Will create a channel without a name.
erikchen99fbfc662016-04-08 22:37:4845 Worker(Channel::Mode mode,
46 const std::string& thread_name,
sammc4bcc4ed62016-10-27 10:13:5947 mojo::ScopedMessagePipeHandle channel_handle)
gab90c2c5c2016-06-01 20:34:0648 : done_(
49 new WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
50 base::WaitableEvent::InitialState::NOT_SIGNALED)),
51 channel_created_(
52 new WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
53 base::WaitableEvent::InitialState::NOT_SIGNALED)),
sammc4bcc4ed62016-10-27 10:13:5954 channel_handle_(std::move(channel_handle)),
initial.commit09911bf2008-07-26 23:55:2955 mode_(mode),
56 ipc_thread_((thread_name + "_ipc").c_str()),
57 listener_thread_((thread_name + "_listener").c_str()),
[email protected]8930d472009-02-21 08:05:2858 overrided_thread_(NULL),
gab90c2c5c2016-06-01 20:34:0659 shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL,
60 base::WaitableEvent::InitialState::NOT_SIGNALED),
erikchen99fbfc662016-04-08 22:37:4861 is_shutdown_(false) {}
initial.commit09911bf2008-07-26 23:55:2962
63 // Will create a named channel and use this name for the threads' name.
sammc4bcc4ed62016-10-27 10:13:5964 Worker(mojo::ScopedMessagePipeHandle channel_handle, Channel::Mode mode)
gab90c2c5c2016-06-01 20:34:0665 : done_(
66 new WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
67 base::WaitableEvent::InitialState::NOT_SIGNALED)),
68 channel_created_(
69 new WaitableEvent(base::WaitableEvent::ResetPolicy::AUTOMATIC,
70 base::WaitableEvent::InitialState::NOT_SIGNALED)),
sammc4bcc4ed62016-10-27 10:13:5971 channel_handle_(std::move(channel_handle)),
initial.commit09911bf2008-07-26 23:55:2972 mode_(mode),
sammc4bcc4ed62016-10-27 10:13:5973 ipc_thread_("ipc thread"),
74 listener_thread_("listener thread"),
[email protected]8930d472009-02-21 08:05:2875 overrided_thread_(NULL),
gab90c2c5c2016-06-01 20:34:0676 shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL,
77 base::WaitableEvent::InitialState::NOT_SIGNALED),
78 is_shutdown_(false) {}
initial.commit09911bf2008-07-26 23:55:2979
dchengfe61fca2014-10-22 02:29:5280 ~Worker() override {
[email protected]bf2a9092013-01-08 06:09:0781 // Shutdown() must be called before destruction.
82 CHECK(is_shutdown_);
initial.commit09911bf2008-07-26 23:55:2983 }
dchengfe61fca2014-10-22 02:29:5284 bool Send(Message* msg) override { return channel_->Send(msg); }
[email protected]aa96ae772009-01-20 22:08:1585 void WaitForChannelCreation() { channel_created_->Wait(); }
[email protected]3cdb7af812008-10-24 19:21:1386 void CloseChannel() {
fdoraybcb9b322016-06-20 20:23:3287 DCHECK(ListenerThread()->task_runner()->BelongsToCurrentThread());
[email protected]3cdb7af812008-10-24 19:21:1388 channel_->Close();
89 }
initial.commit09911bf2008-07-26 23:55:2990 void Start() {
[email protected]fd0a773a2013-04-30 20:55:0391 StartThread(&listener_thread_, base::MessageLoop::TYPE_DEFAULT);
skyostile687bdff2015-05-12 11:29:2192 ListenerThread()->task_runner()->PostTask(
tzik9805c862017-07-06 00:15:5193 FROM_HERE, base::Bind(&Worker::OnStart, base::Unretained(this)));
initial.commit09911bf2008-07-26 23:55:2994 }
[email protected]bf2a9092013-01-08 06:09:0795 void Shutdown() {
96 // The IPC thread needs to outlive SyncChannel. We can't do this in
97 // ~Worker(), since that'll reset the vtable pointer (to Worker's), which
98 // may result in a race conditions. See http://crbug.com/25841.
gab90c2c5c2016-06-01 20:34:0699 WaitableEvent listener_done(
100 base::WaitableEvent::ResetPolicy::AUTOMATIC,
101 base::WaitableEvent::InitialState::NOT_SIGNALED),
102 ipc_done(base::WaitableEvent::ResetPolicy::AUTOMATIC,
103 base::WaitableEvent::InitialState::NOT_SIGNALED);
skyostile687bdff2015-05-12 11:29:21104 ListenerThread()->task_runner()->PostTask(
tzik9805c862017-07-06 00:15:51105 FROM_HERE,
106 base::Bind(&Worker::OnListenerThreadShutdown1, base::Unretained(this),
107 &listener_done, &ipc_done));
[email protected]bf2a9092013-01-08 06:09:07108 listener_done.Wait();
109 ipc_done.Wait();
110 ipc_thread_.Stop();
111 listener_thread_.Stop();
112 is_shutdown_ = true;
113 }
[email protected]ab820df2008-08-26 05:55:10114 void OverrideThread(base::Thread* overrided_thread) {
initial.commit09911bf2008-07-26 23:55:29115 DCHECK(overrided_thread_ == NULL);
116 overrided_thread_ = overrided_thread;
117 }
[email protected]5855f1d2014-04-16 16:50:43118 bool SendAnswerToLife(bool pump, bool succeed) {
[email protected]4df10d612008-11-12 00:38:26119 int answer = 0;
120 SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
121 if (pump)
122 msg->EnableMessagePumping();
[email protected]5855f1d2014-04-16 16:50:43123 bool result = Send(msg);
[email protected]9eec2252009-12-01 02:34:18124 DCHECK_EQ(result, succeed);
125 DCHECK_EQ(answer, (succeed ? 42 : 0));
[email protected]4df10d612008-11-12 00:38:26126 return result;
127 }
128 bool SendDouble(bool pump, bool succeed) {
129 int answer = 0;
130 SyncMessage* msg = new SyncChannelTestMsg_Double(5, &answer);
131 if (pump)
132 msg->EnableMessagePumping();
133 bool result = Send(msg);
[email protected]9eec2252009-12-01 02:34:18134 DCHECK_EQ(result, succeed);
135 DCHECK_EQ(answer, (succeed ? 10 : 0));
[email protected]4df10d612008-11-12 00:38:26136 return result;
137 }
sammc4bcc4ed62016-10-27 10:13:59138 mojo::MessagePipeHandle TakeChannelHandle() {
139 DCHECK(channel_handle_.is_valid());
140 return channel_handle_.release();
141 }
initial.commit09911bf2008-07-26 23:55:29142 Channel::Mode mode() { return mode_; }
[email protected]aa96ae772009-01-20 22:08:15143 WaitableEvent* done_event() { return done_.get(); }
[email protected]1e9499c2010-04-06 20:33:36144 WaitableEvent* shutdown_event() { return &shutdown_event_; }
[email protected]9eec2252009-12-01 02:34:18145 void ResetChannel() { channel_.reset(); }
initial.commit09911bf2008-07-26 23:55:29146 // Derived classes need to call this when they've completed their part of
147 // the test.
[email protected]aa96ae772009-01-20 22:08:15148 void Done() { done_->Signal(); }
[email protected]1e9499c2010-04-06 20:33:36149
150 protected:
[email protected]c9e0c7332011-05-13 22:42:41151 SyncChannel* channel() { return channel_.get(); }
thakisb25789fb2015-04-23 05:40:02152 // Functions for derived classes to implement if they wish.
initial.commit09911bf2008-07-26 23:55:29153 virtual void Run() { }
initial.commit09911bf2008-07-26 23:55:29154 virtual void OnAnswer(int* answer) { NOTREACHED(); }
155 virtual void OnAnswerDelay(Message* reply_msg) {
156 // The message handler map below can only take one entry for
157 // SyncChannelTestMsg_AnswerToLife, so since some classes want
158 // the normal version while other want the delayed reply, we
159 // call the normal version if the derived class didn't override
160 // this function.
161 int answer;
162 OnAnswer(&answer);
163 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, answer);
164 Send(reply_msg);
165 }
[email protected]3cdb7af812008-10-24 19:21:13166 virtual void OnDouble(int in, int* out) { NOTREACHED(); }
167 virtual void OnDoubleDelay(int in, Message* reply_msg) {
168 int result;
169 OnDouble(in, &result);
170 SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, result);
171 Send(reply_msg);
172 }
initial.commit09911bf2008-07-26 23:55:29173
[email protected]ac0efda2009-10-14 16:22:02174 virtual void OnNestedTestMsg(Message* reply_msg) {
175 NOTREACHED();
176 }
177
[email protected]952394af2011-11-16 01:06:46178 virtual SyncChannel* CreateChannel() {
Hajime Hoshiff15e972017-11-09 06:37:09179 std::unique_ptr<SyncChannel> channel = SyncChannel::Create(
180 TakeChannelHandle(), mode_, this, ipc_thread_.task_runner(),
181 base::ThreadTaskRunnerHandle::Get(), true, &shutdown_event_);
[email protected]fca876a12014-06-05 16:15:38182 return channel.release();
[email protected]952394af2011-11-16 01:06:46183 }
184
[email protected]3cdb7af812008-10-24 19:21:13185 base::Thread* ListenerThread() {
186 return overrided_thread_ ? overrided_thread_ : &listener_thread_;
187 }
[email protected]87339f02010-09-02 21:45:50188
[email protected]54af05f2011-04-08 03:38:21189 const base::Thread& ipc_thread() const { return ipc_thread_; }
190
[email protected]87339f02010-09-02 21:45:50191 private:
initial.commit09911bf2008-07-26 23:55:29192 // Called on the listener thread to create the sync channel.
193 void OnStart() {
initial.commit09911bf2008-07-26 23:55:29194 // Link ipc_thread_, listener_thread_ and channel_ altogether.
[email protected]fd0a773a2013-04-30 20:55:03195 StartThread(&ipc_thread_, base::MessageLoop::TYPE_IO);
[email protected]952394af2011-11-16 01:06:46196 channel_.reset(CreateChannel());
[email protected]aa96ae772009-01-20 22:08:15197 channel_created_->Signal();
initial.commit09911bf2008-07-26 23:55:29198 Run();
199 }
200
[email protected]9d4ff5ed2009-03-03 00:21:56201 void OnListenerThreadShutdown1(WaitableEvent* listener_event,
202 WaitableEvent* ipc_event) {
[email protected]3cdb7af812008-10-24 19:21:13203 // SyncChannel needs to be destructed on the thread that it was created on.
204 channel_.reset();
[email protected]9d4ff5ed2009-03-03 00:21:56205
[email protected]2d6e6a72013-02-08 20:11:02206 base::RunLoop().RunUntilIdle();
[email protected]aa96ae772009-01-20 22:08:15207
fdoray8e32586852016-06-22 19:56:16208 ipc_thread_.task_runner()->PostTask(
tzik9805c862017-07-06 00:15:51209 FROM_HERE,
210 base::Bind(&Worker::OnIPCThreadShutdown, base::Unretained(this),
211 listener_event, ipc_event));
[email protected]3cdb7af812008-10-24 19:21:13212 }
213
[email protected]9d4ff5ed2009-03-03 00:21:56214 void OnIPCThreadShutdown(WaitableEvent* listener_event,
215 WaitableEvent* ipc_event) {
[email protected]2d6e6a72013-02-08 20:11:02216 base::RunLoop().RunUntilIdle();
[email protected]aa96ae772009-01-20 22:08:15217 ipc_event->Signal();
[email protected]9d4ff5ed2009-03-03 00:21:56218
skyostile687bdff2015-05-12 11:29:21219 listener_thread_.task_runner()->PostTask(
tzik9805c862017-07-06 00:15:51220 FROM_HERE, base::Bind(&Worker::OnListenerThreadShutdown2,
221 base::Unretained(this), listener_event));
[email protected]9d4ff5ed2009-03-03 00:21:56222 }
223
224 void OnListenerThreadShutdown2(WaitableEvent* listener_event) {
[email protected]2d6e6a72013-02-08 20:11:02225 base::RunLoop().RunUntilIdle();
[email protected]9d4ff5ed2009-03-03 00:21:56226 listener_event->Signal();
[email protected]3cdb7af812008-10-24 19:21:13227 }
228
dchengfe61fca2014-10-22 02:29:52229 bool OnMessageReceived(const Message& message) override {
initial.commit09911bf2008-07-26 23:55:29230 IPC_BEGIN_MESSAGE_MAP(Worker, message)
[email protected]3cdb7af812008-10-24 19:21:13231 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_Double, OnDoubleDelay)
initial.commit09911bf2008-07-26 23:55:29232 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_AnswerToLife,
233 OnAnswerDelay)
[email protected]ac0efda2009-10-14 16:22:02234 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelNestedTestMsg_String,
235 OnNestedTestMsg)
initial.commit09911bf2008-07-26 23:55:29236 IPC_END_MESSAGE_MAP()
[email protected]a95986a82010-12-24 06:19:28237 return true;
initial.commit09911bf2008-07-26 23:55:29238 }
239
[email protected]fd0a773a2013-04-30 20:55:03240 void StartThread(base::Thread* thread, base::MessageLoop::Type type) {
[email protected]ab820df2008-08-26 05:55:10241 base::Thread::Options options;
[email protected]17b89142008-11-07 21:52:15242 options.message_loop_type = type;
[email protected]ab820df2008-08-26 05:55:10243 thread->StartWithOptions(options);
244 }
245
danakj03de39b22016-04-23 04:21:09246 std::unique_ptr<WaitableEvent> done_;
247 std::unique_ptr<WaitableEvent> channel_created_;
sammc4bcc4ed62016-10-27 10:13:59248 mojo::ScopedMessagePipeHandle channel_handle_;
initial.commit09911bf2008-07-26 23:55:29249 Channel::Mode mode_;
danakj03de39b22016-04-23 04:21:09250 std::unique_ptr<SyncChannel> channel_;
[email protected]ab820df2008-08-26 05:55:10251 base::Thread ipc_thread_;
252 base::Thread listener_thread_;
253 base::Thread* overrided_thread_;
initial.commit09911bf2008-07-26 23:55:29254
[email protected]8930d472009-02-21 08:05:28255 base::WaitableEvent shutdown_event_;
256
[email protected]bf2a9092013-01-08 06:09:07257 bool is_shutdown_;
258
[email protected]73a797fb2010-06-07 02:10:18259 DISALLOW_COPY_AND_ASSIGN(Worker);
initial.commit09911bf2008-07-26 23:55:29260};
261
262
263// Starts the test with the given workers. This function deletes the workers
264// when it's done.
265void RunTest(std::vector<Worker*> workers) {
initial.commit09911bf2008-07-26 23:55:29266 // First we create the workers that are channel servers, or else the other
267 // workers' channel initialization might fail because the pipe isn't created..
268 for (size_t i = 0; i < workers.size(); ++i) {
[email protected]1707726c2011-02-03 20:35:09269 if (workers[i]->mode() & Channel::MODE_SERVER_FLAG) {
initial.commit09911bf2008-07-26 23:55:29270 workers[i]->Start();
271 workers[i]->WaitForChannelCreation();
272 }
273 }
274
275 // now create the clients
276 for (size_t i = 0; i < workers.size(); ++i) {
[email protected]1707726c2011-02-03 20:35:09277 if (workers[i]->mode() & Channel::MODE_CLIENT_FLAG)
initial.commit09911bf2008-07-26 23:55:29278 workers[i]->Start();
279 }
280
281 // wait for all the workers to finish
initial.commit09911bf2008-07-26 23:55:29282 for (size_t i = 0; i < workers.size(); ++i)
[email protected]aa96ae772009-01-20 22:08:15283 workers[i]->done_event()->Wait();
initial.commit09911bf2008-07-26 23:55:29284
[email protected]bf2a9092013-01-08 06:09:07285 for (size_t i = 0; i < workers.size(); ++i) {
286 workers[i]->Shutdown();
287 delete workers[i];
288 }
initial.commit09911bf2008-07-26 23:55:29289}
290
[email protected]9629c0e2009-02-04 23:16:29291class IPCSyncChannelTest : public testing::Test {
292 private:
[email protected]fd0a773a2013-04-30 20:55:03293 base::MessageLoop message_loop_;
[email protected]9629c0e2009-02-04 23:16:29294};
295
[email protected]2a3aa7b52013-01-11 20:56:22296//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34297
initial.commit09911bf2008-07-26 23:55:29298class SimpleServer : public Worker {
299 public:
sammc4bcc4ed62016-10-27 10:13:59300 SimpleServer(bool pump_during_send,
301 mojo::ScopedMessagePipeHandle channel_handle)
302 : Worker(Channel::MODE_SERVER,
303 "simpler_server",
304 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:48305 pump_during_send_(pump_during_send) {}
dchengfe61fca2014-10-22 02:29:52306 void Run() override {
[email protected]5855f1d2014-04-16 16:50:43307 SendAnswerToLife(pump_during_send_, true);
initial.commit09911bf2008-07-26 23:55:29308 Done();
309 }
[email protected]3cdb7af812008-10-24 19:21:13310
311 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29312};
313
314class SimpleClient : public Worker {
315 public:
sammc4bcc4ed62016-10-27 10:13:59316 explicit SimpleClient(mojo::ScopedMessagePipeHandle channel_handle)
317 : Worker(Channel::MODE_CLIENT,
318 "simple_client",
319 std::move(channel_handle)) {}
initial.commit09911bf2008-07-26 23:55:29320
dchengfe61fca2014-10-22 02:29:52321 void OnAnswer(int* answer) override {
initial.commit09911bf2008-07-26 23:55:29322 *answer = 42;
323 Done();
324 }
325};
326
[email protected]3cdb7af812008-10-24 19:21:13327void Simple(bool pump_during_send) {
initial.commit09911bf2008-07-26 23:55:29328 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59329 mojo::MessagePipe pipe;
330 workers.push_back(
331 new SimpleServer(pump_during_send, std::move(pipe.handle0)));
332 workers.push_back(new SimpleClient(std::move(pipe.handle1)));
initial.commit09911bf2008-07-26 23:55:29333 RunTest(workers);
334}
335
tfarina8514f0d2015-07-28 14:41:47336#if defined(OS_ANDROID)
337#define MAYBE_Simple DISABLED_Simple
338#else
339#define MAYBE_Simple Simple
340#endif
[email protected]3cdb7af812008-10-24 19:21:13341// Tests basic synchronous call
tfarina8514f0d2015-07-28 14:41:47342TEST_F(IPCSyncChannelTest, MAYBE_Simple) {
[email protected]3cdb7af812008-10-24 19:21:13343 Simple(false);
344 Simple(true);
345}
initial.commit09911bf2008-07-26 23:55:29346
[email protected]2a3aa7b52013-01-11 20:56:22347//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34348
[email protected]952394af2011-11-16 01:06:46349// Worker classes which override how the sync channel is created to use the
350// two-step initialization (calling the lightweight constructor and then
351// ChannelProxy::Init separately) process.
352class TwoStepServer : public Worker {
353 public:
sammc4bcc4ed62016-10-27 10:13:59354 TwoStepServer(bool create_pipe_now,
355 mojo::ScopedMessagePipeHandle channel_handle)
356 : Worker(Channel::MODE_SERVER,
357 "simpler_server",
358 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:48359 create_pipe_now_(create_pipe_now) {}
[email protected]952394af2011-11-16 01:06:46360
dchengfe61fca2014-10-22 02:29:52361 void Run() override {
[email protected]5855f1d2014-04-16 16:50:43362 SendAnswerToLife(false, true);
[email protected]952394af2011-11-16 01:06:46363 Done();
364 }
365
dchengfe61fca2014-10-22 02:29:52366 SyncChannel* CreateChannel() override {
[email protected]fca876a12014-06-05 16:15:38367 SyncChannel* channel =
sammc4bcc4ed62016-10-27 10:13:59368 SyncChannel::Create(TakeChannelHandle(), mode(), this,
Hajime Hoshiff15e972017-11-09 06:37:09369 ipc_thread().task_runner(),
370 base::ThreadTaskRunnerHandle::Get(),
371 create_pipe_now_, shutdown_event())
erikchen30dc2812015-09-24 03:26:38372 .release();
[email protected]952394af2011-11-16 01:06:46373 return channel;
374 }
375
376 bool create_pipe_now_;
377};
378
379class TwoStepClient : public Worker {
380 public:
sammc4bcc4ed62016-10-27 10:13:59381 TwoStepClient(bool create_pipe_now,
382 mojo::ScopedMessagePipeHandle channel_handle)
383 : Worker(Channel::MODE_CLIENT,
384 "simple_client",
385 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:48386 create_pipe_now_(create_pipe_now) {}
[email protected]952394af2011-11-16 01:06:46387
dchengfe61fca2014-10-22 02:29:52388 void OnAnswer(int* answer) override {
[email protected]952394af2011-11-16 01:06:46389 *answer = 42;
390 Done();
391 }
392
dchengfe61fca2014-10-22 02:29:52393 SyncChannel* CreateChannel() override {
[email protected]fca876a12014-06-05 16:15:38394 SyncChannel* channel =
sammc4bcc4ed62016-10-27 10:13:59395 SyncChannel::Create(TakeChannelHandle(), mode(), this,
Hajime Hoshiff15e972017-11-09 06:37:09396 ipc_thread().task_runner(),
397 base::ThreadTaskRunnerHandle::Get(),
398 create_pipe_now_, shutdown_event())
erikchen30dc2812015-09-24 03:26:38399 .release();
[email protected]952394af2011-11-16 01:06:46400 return channel;
401 }
402
403 bool create_pipe_now_;
404};
405
406void TwoStep(bool create_server_pipe_now, bool create_client_pipe_now) {
407 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59408 mojo::MessagePipe pipe;
409 workers.push_back(
410 new TwoStepServer(create_server_pipe_now, std::move(pipe.handle0)));
411 workers.push_back(
412 new TwoStepClient(create_client_pipe_now, std::move(pipe.handle1)));
[email protected]952394af2011-11-16 01:06:46413 RunTest(workers);
414}
415
[email protected]952394af2011-11-16 01:06:46416// Tests basic two-step initialization, where you call the lightweight
417// constructor then Init.
418TEST_F(IPCSyncChannelTest, TwoStepInitialization) {
419 TwoStep(false, false);
420 TwoStep(false, true);
421 TwoStep(true, false);
422 TwoStep(true, true);
423}
424
[email protected]2a3aa7b52013-01-11 20:56:22425//------------------------------------------------------------------------------
[email protected]952394af2011-11-16 01:06:46426
initial.commit09911bf2008-07-26 23:55:29427class DelayClient : public Worker {
428 public:
sammc4bcc4ed62016-10-27 10:13:59429 explicit DelayClient(mojo::ScopedMessagePipeHandle channel_handle)
430 : Worker(Channel::MODE_CLIENT,
431 "delay_client",
432 std::move(channel_handle)) {}
initial.commit09911bf2008-07-26 23:55:29433
dchengfe61fca2014-10-22 02:29:52434 void OnAnswerDelay(Message* reply_msg) override {
initial.commit09911bf2008-07-26 23:55:29435 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
436 Send(reply_msg);
437 Done();
438 }
439};
440
[email protected]3cdb7af812008-10-24 19:21:13441void DelayReply(bool pump_during_send) {
initial.commit09911bf2008-07-26 23:55:29442 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59443 mojo::MessagePipe pipe;
444 workers.push_back(
445 new SimpleServer(pump_during_send, std::move(pipe.handle0)));
446 workers.push_back(new DelayClient(std::move(pipe.handle1)));
initial.commit09911bf2008-07-26 23:55:29447 RunTest(workers);
448}
449
[email protected]3cdb7af812008-10-24 19:21:13450// Tests that asynchronous replies work
451TEST_F(IPCSyncChannelTest, DelayReply) {
452 DelayReply(false);
453 DelayReply(true);
454}
initial.commit09911bf2008-07-26 23:55:29455
[email protected]2a3aa7b52013-01-11 20:56:22456//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34457
initial.commit09911bf2008-07-26 23:55:29458class NoHangServer : public Worker {
459 public:
erikchen99fbfc662016-04-08 22:37:48460 NoHangServer(WaitableEvent* got_first_reply,
461 bool pump_during_send,
sammc4bcc4ed62016-10-27 10:13:59462 mojo::ScopedMessagePipeHandle channel_handle)
463 : Worker(Channel::MODE_SERVER,
464 "no_hang_server",
465 std::move(channel_handle)),
[email protected]3cdb7af812008-10-24 19:21:13466 got_first_reply_(got_first_reply),
erikchen99fbfc662016-04-08 22:37:48467 pump_during_send_(pump_during_send) {}
dchengfe61fca2014-10-22 02:29:52468 void Run() override {
[email protected]5855f1d2014-04-16 16:50:43469 SendAnswerToLife(pump_during_send_, true);
[email protected]aa96ae772009-01-20 22:08:15470 got_first_reply_->Signal();
initial.commit09911bf2008-07-26 23:55:29471
[email protected]5855f1d2014-04-16 16:50:43472 SendAnswerToLife(pump_during_send_, false);
initial.commit09911bf2008-07-26 23:55:29473 Done();
474 }
475
[email protected]aa96ae772009-01-20 22:08:15476 WaitableEvent* got_first_reply_;
[email protected]3cdb7af812008-10-24 19:21:13477 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29478};
479
480class NoHangClient : public Worker {
481 public:
sammc4bcc4ed62016-10-27 10:13:59482 NoHangClient(WaitableEvent* got_first_reply,
483 mojo::ScopedMessagePipeHandle channel_handle)
484 : Worker(Channel::MODE_CLIENT,
485 "no_hang_client",
486 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:48487 got_first_reply_(got_first_reply) {}
initial.commit09911bf2008-07-26 23:55:29488
dchengfe61fca2014-10-22 02:29:52489 void OnAnswerDelay(Message* reply_msg) override {
initial.commit09911bf2008-07-26 23:55:29490 // Use the DELAY_REPLY macro so that we can force the reply to be sent
491 // before this function returns (when the channel will be reset).
492 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
493 Send(reply_msg);
494 got_first_reply_->Wait();
495 CloseChannel();
496 Done();
497 }
498
[email protected]aa96ae772009-01-20 22:08:15499 WaitableEvent* got_first_reply_;
initial.commit09911bf2008-07-26 23:55:29500};
501
[email protected]3cdb7af812008-10-24 19:21:13502void NoHang(bool pump_during_send) {
gab90c2c5c2016-06-01 20:34:06503 WaitableEvent got_first_reply(
504 base::WaitableEvent::ResetPolicy::AUTOMATIC,
505 base::WaitableEvent::InitialState::NOT_SIGNALED);
initial.commit09911bf2008-07-26 23:55:29506 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59507 mojo::MessagePipe pipe;
508 workers.push_back(new NoHangServer(&got_first_reply, pump_during_send,
509 std::move(pipe.handle0)));
erikchen99fbfc662016-04-08 22:37:48510 workers.push_back(
sammc4bcc4ed62016-10-27 10:13:59511 new NoHangClient(&got_first_reply, std::move(pipe.handle1)));
initial.commit09911bf2008-07-26 23:55:29512 RunTest(workers);
513}
514
[email protected]3cdb7af812008-10-24 19:21:13515// Tests that caller doesn't hang if receiver dies
516TEST_F(IPCSyncChannelTest, NoHang) {
517 NoHang(false);
518 NoHang(true);
519}
initial.commit09911bf2008-07-26 23:55:29520
[email protected]2a3aa7b52013-01-11 20:56:22521//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34522
[email protected]3cdb7af812008-10-24 19:21:13523class UnblockServer : public Worker {
initial.commit09911bf2008-07-26 23:55:29524 public:
erikchen99fbfc662016-04-08 22:37:48525 UnblockServer(bool pump_during_send,
526 bool delete_during_send,
sammc4bcc4ed62016-10-27 10:13:59527 mojo::ScopedMessagePipeHandle channel_handle)
528 : Worker(Channel::MODE_SERVER,
529 "unblock_server",
530 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:48531 pump_during_send_(pump_during_send),
532 delete_during_send_(delete_during_send) {}
dchengfe61fca2014-10-22 02:29:52533 void Run() override {
[email protected]9eec2252009-12-01 02:34:18534 if (delete_during_send_) {
535 // Use custom code since race conditions mean the answer may or may not be
536 // available.
537 int answer = 0;
538 SyncMessage* msg = new SyncChannelTestMsg_AnswerToLife(&answer);
539 if (pump_during_send_)
540 msg->EnableMessagePumping();
541 Send(msg);
542 } else {
[email protected]5855f1d2014-04-16 16:50:43543 SendAnswerToLife(pump_during_send_, true);
[email protected]9eec2252009-12-01 02:34:18544 }
initial.commit09911bf2008-07-26 23:55:29545 Done();
546 }
547
dchengfe61fca2014-10-22 02:29:52548 void OnDoubleDelay(int in, Message* reply_msg) override {
[email protected]9eec2252009-12-01 02:34:18549 SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, in * 2);
550 Send(reply_msg);
551 if (delete_during_send_)
552 ResetChannel();
initial.commit09911bf2008-07-26 23:55:29553 }
[email protected]3cdb7af812008-10-24 19:21:13554
555 bool pump_during_send_;
[email protected]9eec2252009-12-01 02:34:18556 bool delete_during_send_;
initial.commit09911bf2008-07-26 23:55:29557};
558
[email protected]3cdb7af812008-10-24 19:21:13559class UnblockClient : public Worker {
initial.commit09911bf2008-07-26 23:55:29560 public:
sammc4bcc4ed62016-10-27 10:13:59561 UnblockClient(bool pump_during_send,
562 mojo::ScopedMessagePipeHandle channel_handle)
563 : Worker(Channel::MODE_CLIENT,
564 "unblock_client",
565 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:48566 pump_during_send_(pump_during_send) {}
initial.commit09911bf2008-07-26 23:55:29567
dchengfe61fca2014-10-22 02:29:52568 void OnAnswer(int* answer) override {
[email protected]4df10d612008-11-12 00:38:26569 SendDouble(pump_during_send_, true);
570 *answer = 42;
initial.commit09911bf2008-07-26 23:55:29571 Done();
572 }
[email protected]3cdb7af812008-10-24 19:21:13573
574 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29575};
576
[email protected]9eec2252009-12-01 02:34:18577void Unblock(bool server_pump, bool client_pump, bool delete_during_send) {
[email protected]3cdb7af812008-10-24 19:21:13578 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59579 mojo::MessagePipe pipe;
580 workers.push_back(new UnblockServer(server_pump, delete_during_send,
581 std::move(pipe.handle0)));
582 workers.push_back(new UnblockClient(client_pump, std::move(pipe.handle1)));
[email protected]3cdb7af812008-10-24 19:21:13583 RunTest(workers);
584}
585
initial.commit09911bf2008-07-26 23:55:29586// Tests that the caller unblocks to answer a sync message from the receiver.
[email protected]3cdb7af812008-10-24 19:21:13587TEST_F(IPCSyncChannelTest, Unblock) {
[email protected]9eec2252009-12-01 02:34:18588 Unblock(false, false, false);
589 Unblock(false, true, false);
590 Unblock(true, false, false);
591 Unblock(true, true, false);
592}
593
[email protected]2a3aa7b52013-01-11 20:56:22594//------------------------------------------------------------------------------
[email protected]9eec2252009-12-01 02:34:18595
tfarina8514f0d2015-07-28 14:41:47596#if defined(OS_ANDROID)
597#define MAYBE_ChannelDeleteDuringSend DISABLED_ChannelDeleteDuringSend
598#else
599#define MAYBE_ChannelDeleteDuringSend ChannelDeleteDuringSend
600#endif
[email protected]c9e0c7332011-05-13 22:42:41601// Tests that the the SyncChannel object can be deleted during a Send.
tfarina8514f0d2015-07-28 14:41:47602TEST_F(IPCSyncChannelTest, MAYBE_ChannelDeleteDuringSend) {
[email protected]9eec2252009-12-01 02:34:18603 Unblock(false, false, true);
604 Unblock(false, true, true);
605 Unblock(true, false, true);
606 Unblock(true, true, true);
[email protected]3cdb7af812008-10-24 19:21:13607}
608
[email protected]2a3aa7b52013-01-11 20:56:22609//------------------------------------------------------------------------------
[email protected]3cdb7af812008-10-24 19:21:13610
611class RecursiveServer : public Worker {
612 public:
erikchen99fbfc662016-04-08 22:37:48613 RecursiveServer(bool expected_send_result,
614 bool pump_first,
615 bool pump_second,
sammc4bcc4ed62016-10-27 10:13:59616 mojo::ScopedMessagePipeHandle channel_handle)
617 : Worker(Channel::MODE_SERVER,
618 "recursive_server",
619 std::move(channel_handle)),
[email protected]e7e38032011-07-26 17:25:25620 expected_send_result_(expected_send_result),
erikchen99fbfc662016-04-08 22:37:48621 pump_first_(pump_first),
622 pump_second_(pump_second) {}
dchengfe61fca2014-10-22 02:29:52623 void Run() override {
[email protected]4df10d612008-11-12 00:38:26624 SendDouble(pump_first_, expected_send_result_);
[email protected]3cdb7af812008-10-24 19:21:13625 Done();
626 }
627
dchengfe61fca2014-10-22 02:29:52628 void OnDouble(int in, int* out) override {
[email protected]4df10d612008-11-12 00:38:26629 *out = in * 2;
[email protected]5855f1d2014-04-16 16:50:43630 SendAnswerToLife(pump_second_, expected_send_result_);
[email protected]3cdb7af812008-10-24 19:21:13631 }
632
633 bool expected_send_result_, pump_first_, pump_second_;
634};
635
636class RecursiveClient : public Worker {
637 public:
erikchen99fbfc662016-04-08 22:37:48638 RecursiveClient(bool pump_during_send,
639 bool close_channel,
sammc4bcc4ed62016-10-27 10:13:59640 mojo::ScopedMessagePipeHandle channel_handle)
641 : Worker(Channel::MODE_CLIENT,
642 "recursive_client",
643 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:48644 pump_during_send_(pump_during_send),
645 close_channel_(close_channel) {}
[email protected]3cdb7af812008-10-24 19:21:13646
dchengfe61fca2014-10-22 02:29:52647 void OnDoubleDelay(int in, Message* reply_msg) override {
[email protected]4df10d612008-11-12 00:38:26648 SendDouble(pump_during_send_, !close_channel_);
[email protected]c690a182008-10-24 23:10:32649 if (close_channel_) {
650 delete reply_msg;
651 } else {
[email protected]3cdb7af812008-10-24 19:21:13652 SyncChannelTestMsg_Double::WriteReplyParams(reply_msg, in * 2);
653 Send(reply_msg);
654 }
655 Done();
656 }
657
dchengfe61fca2014-10-22 02:29:52658 void OnAnswerDelay(Message* reply_msg) override {
[email protected]3cdb7af812008-10-24 19:21:13659 if (close_channel_) {
[email protected]c690a182008-10-24 23:10:32660 delete reply_msg;
[email protected]3cdb7af812008-10-24 19:21:13661 CloseChannel();
662 } else {
663 SyncChannelTestMsg_AnswerToLife::WriteReplyParams(reply_msg, 42);
664 Send(reply_msg);
665 }
666 }
667
668 bool pump_during_send_, close_channel_;
669};
670
671void Recursive(
672 bool server_pump_first, bool server_pump_second, bool client_pump) {
initial.commit09911bf2008-07-26 23:55:29673 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59674 mojo::MessagePipe pipe;
675 workers.push_back(new RecursiveServer(
676 true, server_pump_first, server_pump_second, std::move(pipe.handle0)));
677 workers.push_back(
678 new RecursiveClient(client_pump, false, std::move(pipe.handle1)));
initial.commit09911bf2008-07-26 23:55:29679 RunTest(workers);
680}
681
[email protected]3cdb7af812008-10-24 19:21:13682// Tests a server calling Send while another Send is pending.
683TEST_F(IPCSyncChannelTest, Recursive) {
684 Recursive(false, false, false);
685 Recursive(false, false, true);
686 Recursive(false, true, false);
687 Recursive(false, true, true);
688 Recursive(true, false, false);
689 Recursive(true, false, true);
690 Recursive(true, true, false);
691 Recursive(true, true, true);
692}
693
[email protected]2a3aa7b52013-01-11 20:56:22694//------------------------------------------------------------------------------
[email protected]3cdb7af812008-10-24 19:21:13695
696void RecursiveNoHang(
697 bool server_pump_first, bool server_pump_second, bool client_pump) {
698 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59699 mojo::MessagePipe pipe;
700 workers.push_back(new RecursiveServer(
701 false, server_pump_first, server_pump_second, std::move(pipe.handle0)));
702 workers.push_back(
703 new RecursiveClient(client_pump, true, std::move(pipe.handle1)));
[email protected]3cdb7af812008-10-24 19:21:13704 RunTest(workers);
705}
706
[email protected]3cdb7af812008-10-24 19:21:13707// Tests that if a caller makes a sync call during an existing sync call and
708// the receiver dies, neither of the Send() calls hang.
709TEST_F(IPCSyncChannelTest, RecursiveNoHang) {
710 RecursiveNoHang(false, false, false);
711 RecursiveNoHang(false, false, true);
712 RecursiveNoHang(false, true, false);
713 RecursiveNoHang(false, true, true);
714 RecursiveNoHang(true, false, false);
715 RecursiveNoHang(true, false, true);
716 RecursiveNoHang(true, true, false);
717 RecursiveNoHang(true, true, true);
718}
initial.commit09911bf2008-07-26 23:55:29719
[email protected]2a3aa7b52013-01-11 20:56:22720//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34721
initial.commit09911bf2008-07-26 23:55:29722class MultipleServer1 : public Worker {
723 public:
sammc4bcc4ed62016-10-27 10:13:59724 MultipleServer1(bool pump_during_send,
725 mojo::ScopedMessagePipeHandle channel_handle)
726 : Worker(std::move(channel_handle), Channel::MODE_SERVER),
727 pump_during_send_(pump_during_send) {}
[email protected]3cdb7af812008-10-24 19:21:13728
dchengfe61fca2014-10-22 02:29:52729 void Run() override {
[email protected]4df10d612008-11-12 00:38:26730 SendDouble(pump_during_send_, true);
initial.commit09911bf2008-07-26 23:55:29731 Done();
732 }
[email protected]3cdb7af812008-10-24 19:21:13733
734 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29735};
736
737class MultipleClient1 : public Worker {
738 public:
[email protected]aa96ae772009-01-20 22:08:15739 MultipleClient1(WaitableEvent* client1_msg_received,
sammc4bcc4ed62016-10-27 10:13:59740 WaitableEvent* client1_can_reply,
741 mojo::ScopedMessagePipeHandle channel_handle)
742 : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
743 client1_msg_received_(client1_msg_received),
744 client1_can_reply_(client1_can_reply) {}
initial.commit09911bf2008-07-26 23:55:29745
dchengfe61fca2014-10-22 02:29:52746 void OnDouble(int in, int* out) override {
[email protected]aa96ae772009-01-20 22:08:15747 client1_msg_received_->Signal();
initial.commit09911bf2008-07-26 23:55:29748 *out = in * 2;
749 client1_can_reply_->Wait();
750 Done();
751 }
752
753 private:
[email protected]aa96ae772009-01-20 22:08:15754 WaitableEvent *client1_msg_received_, *client1_can_reply_;
initial.commit09911bf2008-07-26 23:55:29755};
756
757class MultipleServer2 : public Worker {
758 public:
sammc4bcc4ed62016-10-27 10:13:59759 explicit MultipleServer2(mojo::ScopedMessagePipeHandle channel_handle)
760 : Worker(std::move(channel_handle), Channel::MODE_SERVER) {}
initial.commit09911bf2008-07-26 23:55:29761
dchengfe61fca2014-10-22 02:29:52762 void OnAnswer(int* result) override {
initial.commit09911bf2008-07-26 23:55:29763 *result = 42;
764 Done();
765 }
766};
767
768class MultipleClient2 : public Worker {
769 public:
sammc4bcc4ed62016-10-27 10:13:59770 MultipleClient2(WaitableEvent* client1_msg_received,
771 WaitableEvent* client1_can_reply,
772 bool pump_during_send,
773 mojo::ScopedMessagePipeHandle channel_handle)
774 : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
775 client1_msg_received_(client1_msg_received),
776 client1_can_reply_(client1_can_reply),
777 pump_during_send_(pump_during_send) {}
initial.commit09911bf2008-07-26 23:55:29778
dchengfe61fca2014-10-22 02:29:52779 void Run() override {
initial.commit09911bf2008-07-26 23:55:29780 client1_msg_received_->Wait();
[email protected]5855f1d2014-04-16 16:50:43781 SendAnswerToLife(pump_during_send_, true);
[email protected]aa96ae772009-01-20 22:08:15782 client1_can_reply_->Signal();
initial.commit09911bf2008-07-26 23:55:29783 Done();
784 }
785
786 private:
[email protected]aa96ae772009-01-20 22:08:15787 WaitableEvent *client1_msg_received_, *client1_can_reply_;
[email protected]3cdb7af812008-10-24 19:21:13788 bool pump_during_send_;
initial.commit09911bf2008-07-26 23:55:29789};
790
[email protected]3cdb7af812008-10-24 19:21:13791void Multiple(bool server_pump, bool client_pump) {
initial.commit09911bf2008-07-26 23:55:29792 std::vector<Worker*> workers;
793
794 // A shared worker thread so that server1 and server2 run on one thread.
[email protected]ab820df2008-08-26 05:55:10795 base::Thread worker_thread("Multiple");
[email protected]6314e6f62009-07-15 16:07:14796 ASSERT_TRUE(worker_thread.Start());
initial.commit09911bf2008-07-26 23:55:29797
798 // Server1 sends a sync msg to client1, which blocks the reply until
799 // server2 (which runs on the same worker thread as server1) responds
800 // to a sync msg from client2.
gab90c2c5c2016-06-01 20:34:06801 WaitableEvent client1_msg_received(
802 base::WaitableEvent::ResetPolicy::AUTOMATIC,
803 base::WaitableEvent::InitialState::NOT_SIGNALED);
804 WaitableEvent client1_can_reply(
805 base::WaitableEvent::ResetPolicy::AUTOMATIC,
806 base::WaitableEvent::InitialState::NOT_SIGNALED);
initial.commit09911bf2008-07-26 23:55:29807
808 Worker* worker;
809
sammc4bcc4ed62016-10-27 10:13:59810 mojo::MessagePipe pipe1, pipe2;
811 worker = new MultipleServer2(std::move(pipe2.handle0));
initial.commit09911bf2008-07-26 23:55:29812 worker->OverrideThread(&worker_thread);
813 workers.push_back(worker);
814
sammc4bcc4ed62016-10-27 10:13:59815 worker = new MultipleClient2(&client1_msg_received, &client1_can_reply,
816 client_pump, std::move(pipe2.handle1));
initial.commit09911bf2008-07-26 23:55:29817 workers.push_back(worker);
818
sammc4bcc4ed62016-10-27 10:13:59819 worker = new MultipleServer1(server_pump, std::move(pipe1.handle0));
initial.commit09911bf2008-07-26 23:55:29820 worker->OverrideThread(&worker_thread);
821 workers.push_back(worker);
822
sammc4bcc4ed62016-10-27 10:13:59823 worker = new MultipleClient1(&client1_msg_received, &client1_can_reply,
824 std::move(pipe1.handle1));
initial.commit09911bf2008-07-26 23:55:29825 workers.push_back(worker);
826
827 RunTest(workers);
828}
829
[email protected]3cdb7af812008-10-24 19:21:13830// Tests that multiple SyncObjects on the same listener thread can unblock each
831// other.
832TEST_F(IPCSyncChannelTest, Multiple) {
833 Multiple(false, false);
834 Multiple(false, true);
835 Multiple(true, false);
836 Multiple(true, true);
837}
initial.commit09911bf2008-07-26 23:55:29838
[email protected]2a3aa7b52013-01-11 20:56:22839//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34840
[email protected]ac0efda2009-10-14 16:22:02841// This class provides server side functionality to test the case where
842// multiple sync channels are in use on the same thread on the client and
843// nested calls are issued.
844class QueuedReplyServer : public Worker {
initial.commit09911bf2008-07-26 23:55:29845 public:
[email protected]b7243c42010-07-23 05:23:13846 QueuedReplyServer(base::Thread* listener_thread,
sammc4bcc4ed62016-10-27 10:13:59847 mojo::ScopedMessagePipeHandle channel_handle,
[email protected]b7243c42010-07-23 05:23:13848 const std::string& reply_text)
sammc4bcc4ed62016-10-27 10:13:59849 : Worker(std::move(channel_handle), Channel::MODE_SERVER),
[email protected]ac0efda2009-10-14 16:22:02850 reply_text_(reply_text) {
851 Worker::OverrideThread(listener_thread);
initial.commit09911bf2008-07-26 23:55:29852 }
[email protected]3cdb7af812008-10-24 19:21:13853
dchengfe61fca2014-10-22 02:29:52854 void OnNestedTestMsg(Message* reply_msg) override {
[email protected]2a9d601b2010-10-19 23:50:00855 VLOG(1) << __FUNCTION__ << " Sending reply: " << reply_text_;
856 SyncChannelNestedTestMsg_String::WriteReplyParams(reply_msg, reply_text_);
[email protected]ac0efda2009-10-14 16:22:02857 Send(reply_msg);
initial.commit09911bf2008-07-26 23:55:29858 Done();
859 }
860
861 private:
[email protected]ac0efda2009-10-14 16:22:02862 std::string reply_text_;
initial.commit09911bf2008-07-26 23:55:29863};
864
[email protected]ac0efda2009-10-14 16:22:02865// The QueuedReplyClient class provides functionality to test the case where
866// multiple sync channels are in use on the same thread and they make nested
867// sync calls, i.e. while the first channel waits for a response it makes a
868// sync call on another channel.
869// The callstack should unwind correctly, i.e. the outermost call should
870// complete first, and so on.
871class QueuedReplyClient : public Worker {
initial.commit09911bf2008-07-26 23:55:29872 public:
[email protected]ac0efda2009-10-14 16:22:02873 QueuedReplyClient(base::Thread* listener_thread,
sammc4bcc4ed62016-10-27 10:13:59874 mojo::ScopedMessagePipeHandle channel_handle,
[email protected]ac0efda2009-10-14 16:22:02875 const std::string& expected_text,
876 bool pump_during_send)
sammc4bcc4ed62016-10-27 10:13:59877 : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
[email protected]7ee1a44c2010-07-23 14:18:59878 pump_during_send_(pump_during_send),
879 expected_text_(expected_text) {
[email protected]ac0efda2009-10-14 16:22:02880 Worker::OverrideThread(listener_thread);
881 }
initial.commit09911bf2008-07-26 23:55:29882
dchengfe61fca2014-10-22 02:29:52883 void Run() override {
[email protected]ac0efda2009-10-14 16:22:02884 std::string response;
885 SyncMessage* msg = new SyncChannelNestedTestMsg_String(&response);
886 if (pump_during_send_)
887 msg->EnableMessagePumping();
888 bool result = Send(msg);
889 DCHECK(result);
[email protected]9eec2252009-12-01 02:34:18890 DCHECK_EQ(response, expected_text_);
initial.commit09911bf2008-07-26 23:55:29891
[email protected]2a9d601b2010-10-19 23:50:00892 VLOG(1) << __FUNCTION__ << " Received reply: " << response;
initial.commit09911bf2008-07-26 23:55:29893 Done();
894 }
895
[email protected]ac0efda2009-10-14 16:22:02896 private:
[email protected]3cdb7af812008-10-24 19:21:13897 bool pump_during_send_;
[email protected]ac0efda2009-10-14 16:22:02898 std::string expected_text_;
initial.commit09911bf2008-07-26 23:55:29899};
900
[email protected]ac0efda2009-10-14 16:22:02901void QueuedReply(bool client_pump) {
initial.commit09911bf2008-07-26 23:55:29902 std::vector<Worker*> workers;
903
[email protected]ac0efda2009-10-14 16:22:02904 // A shared worker thread for servers
905 base::Thread server_worker_thread("QueuedReply_ServerListener");
906 ASSERT_TRUE(server_worker_thread.Start());
initial.commit09911bf2008-07-26 23:55:29907
[email protected]ac0efda2009-10-14 16:22:02908 base::Thread client_worker_thread("QueuedReply_ClientListener");
909 ASSERT_TRUE(client_worker_thread.Start());
initial.commit09911bf2008-07-26 23:55:29910
911 Worker* worker;
912
sammc4bcc4ed62016-10-27 10:13:59913 mojo::MessagePipe pipe1, pipe2;
[email protected]ac0efda2009-10-14 16:22:02914 worker = new QueuedReplyServer(&server_worker_thread,
sammc4bcc4ed62016-10-27 10:13:59915 std::move(pipe1.handle0), "Got first message");
initial.commit09911bf2008-07-26 23:55:29916 workers.push_back(worker);
917
sammc4bcc4ed62016-10-27 10:13:59918 worker = new QueuedReplyServer(
919 &server_worker_thread, std::move(pipe2.handle0), "Got second message");
initial.commit09911bf2008-07-26 23:55:29920 workers.push_back(worker);
921
sammc4bcc4ed62016-10-27 10:13:59922 worker =
923 new QueuedReplyClient(&client_worker_thread, std::move(pipe1.handle1),
924 "Got first message", client_pump);
initial.commit09911bf2008-07-26 23:55:29925 workers.push_back(worker);
926
sammc4bcc4ed62016-10-27 10:13:59927 worker =
928 new QueuedReplyClient(&client_worker_thread, std::move(pipe2.handle1),
929 "Got second message", client_pump);
initial.commit09911bf2008-07-26 23:55:29930 workers.push_back(worker);
931
932 RunTest(workers);
933}
934
[email protected]3cdb7af812008-10-24 19:21:13935// While a blocking send is in progress, the listener thread might answer other
936// synchronous messages. This tests that if during the response to another
937// message the reply to the original messages comes, it is queued up correctly
938// and the original Send is unblocked later.
[email protected]ac0efda2009-10-14 16:22:02939// We also test that the send call stacks unwind correctly when the channel
940// pumps messages while waiting for a response.
[email protected]3cdb7af812008-10-24 19:21:13941TEST_F(IPCSyncChannelTest, QueuedReply) {
[email protected]ac0efda2009-10-14 16:22:02942 QueuedReply(false);
943 QueuedReply(true);
[email protected]3cdb7af812008-10-24 19:21:13944}
initial.commit09911bf2008-07-26 23:55:29945
[email protected]2a3aa7b52013-01-11 20:56:22946//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:34947
[email protected]3cdb7af812008-10-24 19:21:13948class ChattyClient : public Worker {
initial.commit09911bf2008-07-26 23:55:29949 public:
sammc4bcc4ed62016-10-27 10:13:59950 explicit ChattyClient(mojo::ScopedMessagePipeHandle channel_handle)
951 : Worker(Channel::MODE_CLIENT,
952 "chatty_client",
953 std::move(channel_handle)) {}
initial.commit09911bf2008-07-26 23:55:29954
dchengfe61fca2014-10-22 02:29:52955 void OnAnswer(int* answer) override {
initial.commit09911bf2008-07-26 23:55:29956 // The PostMessage limit is 10k. Send 20% more than that.
957 const int kMessageLimit = 10000;
958 const int kMessagesToSend = kMessageLimit * 120 / 100;
959 for (int i = 0; i < kMessagesToSend; ++i) {
[email protected]4df10d612008-11-12 00:38:26960 if (!SendDouble(false, true))
initial.commit09911bf2008-07-26 23:55:29961 break;
962 }
[email protected]4df10d612008-11-12 00:38:26963 *answer = 42;
initial.commit09911bf2008-07-26 23:55:29964 Done();
965 }
966};
967
[email protected]3cdb7af812008-10-24 19:21:13968void ChattyServer(bool pump_during_send) {
969 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:59970 mojo::MessagePipe pipe;
971 workers.push_back(
972 new UnblockServer(pump_during_send, false, std::move(pipe.handle0)));
973 workers.push_back(new ChattyClient(std::move(pipe.handle1)));
[email protected]3cdb7af812008-10-24 19:21:13974 RunTest(workers);
975}
976
tfarina8514f0d2015-07-28 14:41:47977#if defined(OS_ANDROID)
978// Times out.
979#define MAYBE_ChattyServer DISABLED_ChattyServer
980#else
981#define MAYBE_ChattyServer ChattyServer
982#endif
[email protected]4df10d612008-11-12 00:38:26983// Tests http://b/1093251 - that sending lots of sync messages while
initial.commit09911bf2008-07-26 23:55:29984// the receiver is waiting for a sync reply does not overflow the PostMessage
985// queue.
tfarina8514f0d2015-07-28 14:41:47986TEST_F(IPCSyncChannelTest, MAYBE_ChattyServer) {
[email protected]3cdb7af812008-10-24 19:21:13987 ChattyServer(false);
sammc4bcc4ed62016-10-27 10:13:59988}
989
990#if defined(OS_ANDROID)
991// Times out.
992#define MAYBE_ChattyServerPumpDuringSend DISABLED_ChattyServerPumpDuringSend
993#else
994#define MAYBE_ChattyServerPumpDuringSend ChattyServerPumpDuringSend
995#endif
996TEST_F(IPCSyncChannelTest, MAYBE_ChattyServerPumpDuringSend) {
[email protected]3cdb7af812008-10-24 19:21:13997 ChattyServer(true);
initial.commit09911bf2008-07-26 23:55:29998}
[email protected]d65cab7a2008-08-12 01:25:41999
[email protected]d65cab7a2008-08-12 01:25:411000//------------------------------------------------------------------------------
[email protected]dd3eac22008-08-26 07:28:341001
[email protected]0633e3152011-11-28 18:35:391002void NestedCallback(Worker* server) {
1003 // Sleep a bit so that we wake up after the reply has been received.
[email protected]b5393332012-01-13 00:11:011004 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(250));
[email protected]5855f1d2014-04-16 16:50:431005 server->SendAnswerToLife(true, true);
[email protected]0633e3152011-11-28 18:35:391006}
[email protected]4df10d612008-11-12 00:38:261007
[email protected]0633e3152011-11-28 18:35:391008bool timeout_occurred = false;
[email protected]4df10d612008-11-12 00:38:261009
[email protected]0633e3152011-11-28 18:35:391010void TimeoutCallback() {
1011 timeout_occurred = true;
1012}
[email protected]4df10d612008-11-12 00:38:261013
1014class DoneEventRaceServer : public Worker {
1015 public:
sammc4bcc4ed62016-10-27 10:13:591016 explicit DoneEventRaceServer(mojo::ScopedMessagePipeHandle channel_handle)
1017 : Worker(Channel::MODE_SERVER,
1018 "done_event_race_server",
1019 std::move(channel_handle)) {}
[email protected]4df10d612008-11-12 00:38:261020
dchengfe61fca2014-10-22 02:29:521021 void Run() override {
skyostile687bdff2015-05-12 11:29:211022 base::ThreadTaskRunnerHandle::Get()->PostTask(
tzik9805c862017-07-06 00:15:511023 FROM_HERE, base::Bind(&NestedCallback, base::Unretained(this)));
skyostile687bdff2015-05-12 11:29:211024 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1025 FROM_HERE, base::Bind(&TimeoutCallback),
[email protected]5896fa042012-03-07 04:41:401026 base::TimeDelta::FromSeconds(9));
[email protected]4df10d612008-11-12 00:38:261027 // Even though we have a timeout on the Send, it will succeed since for this
1028 // bug, the reply message comes back and is deserialized, however the done
1029 // event wasn't set. So we indirectly use the timeout task to notice if a
1030 // timeout occurred.
[email protected]5855f1d2014-04-16 16:50:431031 SendAnswerToLife(true, true);
[email protected]0633e3152011-11-28 18:35:391032 DCHECK(!timeout_occurred);
[email protected]4df10d612008-11-12 00:38:261033 Done();
1034 }
1035};
1036
tfarina8514f0d2015-07-28 14:41:471037#if defined(OS_ANDROID)
1038#define MAYBE_DoneEventRace DISABLED_DoneEventRace
1039#else
1040#define MAYBE_DoneEventRace DoneEventRace
1041#endif
[email protected]4df10d612008-11-12 00:38:261042// Tests http://b/1474092 - that if after the done_event is set but before
1043// OnObjectSignaled is called another message is sent out, then after its
1044// reply comes back OnObjectSignaled will be called for the first message.
tfarina8514f0d2015-07-28 14:41:471045TEST_F(IPCSyncChannelTest, MAYBE_DoneEventRace) {
[email protected]4df10d612008-11-12 00:38:261046 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:591047 mojo::MessagePipe pipe;
1048 workers.push_back(new DoneEventRaceServer(std::move(pipe.handle0)));
1049 workers.push_back(new SimpleClient(std::move(pipe.handle1)));
[email protected]4df10d612008-11-12 00:38:261050 RunTest(workers);
1051}
[email protected]1e9499c2010-04-06 20:33:361052
[email protected]2a3aa7b52013-01-11 20:56:221053//------------------------------------------------------------------------------
[email protected]1e9499c2010-04-06 20:33:361054
[email protected]c9e0c7332011-05-13 22:42:411055class TestSyncMessageFilter : public SyncMessageFilter {
[email protected]1e9499c2010-04-06 20:33:361056 public:
skyostile687bdff2015-05-12 11:29:211057 TestSyncMessageFilter(
1058 base::WaitableEvent* shutdown_event,
1059 Worker* worker,
1060 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
rockotb97e3d32016-09-16 17:39:031061 : SyncMessageFilter(shutdown_event),
[email protected]1e9499c2010-04-06 20:33:361062 worker_(worker),
skyostile687bdff2015-05-12 11:29:211063 task_runner_(task_runner) {}
[email protected]1e9499c2010-04-06 20:33:361064
rockote0072ebd2016-09-16 23:40:301065 void OnFilterAdded(Channel* channel) override {
1066 SyncMessageFilter::OnFilterAdded(channel);
skyostile687bdff2015-05-12 11:29:211067 task_runner_->PostTask(
[email protected]72b6f8e22011-11-12 21:16:411068 FROM_HERE,
1069 base::Bind(&TestSyncMessageFilter::SendMessageOnHelperThread, this));
[email protected]1e9499c2010-04-06 20:33:361070 }
1071
1072 void SendMessageOnHelperThread() {
1073 int answer = 0;
1074 bool result = Send(new SyncChannelTestMsg_AnswerToLife(&answer));
1075 DCHECK(result);
1076 DCHECK_EQ(answer, 42);
1077
1078 worker_->Done();
1079 }
1080
[email protected]f729d15a2012-04-28 02:12:001081 private:
Chris Watkins2d879af2017-11-30 02:11:591082 ~TestSyncMessageFilter() override = default;
[email protected]f729d15a2012-04-28 02:12:001083
[email protected]1e9499c2010-04-06 20:33:361084 Worker* worker_;
skyostile687bdff2015-05-12 11:29:211085 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
[email protected]1e9499c2010-04-06 20:33:361086};
1087
1088class SyncMessageFilterServer : public Worker {
1089 public:
sammc4bcc4ed62016-10-27 10:13:591090 explicit SyncMessageFilterServer(mojo::ScopedMessagePipeHandle channel_handle)
erikchen99fbfc662016-04-08 22:37:481091 : Worker(Channel::MODE_SERVER,
1092 "sync_message_filter_server",
sammc4bcc4ed62016-10-27 10:13:591093 std::move(channel_handle)),
[email protected]d4fc4d6a2012-09-08 01:24:491094 thread_("helper_thread") {
1095 base::Thread::Options options;
[email protected]fd0a773a2013-04-30 20:55:031096 options.message_loop_type = base::MessageLoop::TYPE_DEFAULT;
[email protected]d4fc4d6a2012-09-08 01:24:491097 thread_.StartWithOptions(options);
1098 filter_ = new TestSyncMessageFilter(shutdown_event(), this,
skyostile687bdff2015-05-12 11:29:211099 thread_.task_runner());
[email protected]1e9499c2010-04-06 20:33:361100 }
1101
dchengfe61fca2014-10-22 02:29:521102 void Run() override {
dchengf3076af2014-10-21 18:02:421103 channel()->AddFilter(filter_.get());
1104 }
[email protected]1e9499c2010-04-06 20:33:361105
[email protected]d4fc4d6a2012-09-08 01:24:491106 base::Thread thread_;
[email protected]1e9499c2010-04-06 20:33:361107 scoped_refptr<TestSyncMessageFilter> filter_;
1108};
1109
[email protected]87339f02010-09-02 21:45:501110// This class provides functionality to test the case that a Send on the sync
1111// channel does not crash after the channel has been closed.
1112class ServerSendAfterClose : public Worker {
1113 public:
sammc4bcc4ed62016-10-27 10:13:591114 explicit ServerSendAfterClose(mojo::ScopedMessagePipeHandle channel_handle)
1115 : Worker(Channel::MODE_SERVER,
1116 "simpler_server",
1117 std::move(channel_handle)),
erikchen99fbfc662016-04-08 22:37:481118 send_result_(true) {}
[email protected]87339f02010-09-02 21:45:501119
1120 bool SendDummy() {
skyostile687bdff2015-05-12 11:29:211121 ListenerThread()->task_runner()->PostTask(
tzik9805c862017-07-06 00:15:511122 FROM_HERE,
1123 base::Bind(base::IgnoreResult(&ServerSendAfterClose::Send),
1124 base::Unretained(this), new SyncChannelTestMsg_NoArgs));
[email protected]87339f02010-09-02 21:45:501125 return true;
1126 }
1127
1128 bool send_result() const {
1129 return send_result_;
1130 }
1131
1132 private:
dchengfe61fca2014-10-22 02:29:521133 void Run() override {
[email protected]87339f02010-09-02 21:45:501134 CloseChannel();
1135 Done();
1136 }
1137
dchengfe61fca2014-10-22 02:29:521138 bool Send(Message* msg) override {
[email protected]87339f02010-09-02 21:45:501139 send_result_ = Worker::Send(msg);
1140 Done();
1141 return send_result_;
1142 }
1143
1144 bool send_result_;
1145};
1146
[email protected]1e9499c2010-04-06 20:33:361147// Tests basic synchronous call
1148TEST_F(IPCSyncChannelTest, SyncMessageFilter) {
1149 std::vector<Worker*> workers;
sammc4bcc4ed62016-10-27 10:13:591150 mojo::MessagePipe pipe;
1151 workers.push_back(new SyncMessageFilterServer(std::move(pipe.handle0)));
1152 workers.push_back(new SimpleClient(std::move(pipe.handle1)));
[email protected]1e9499c2010-04-06 20:33:361153 RunTest(workers);
1154}
[email protected]87339f02010-09-02 21:45:501155
1156// Test the case when the channel is closed and a Send is attempted after that.
1157TEST_F(IPCSyncChannelTest, SendAfterClose) {
sammc4bcc4ed62016-10-27 10:13:591158 mojo::MessagePipe pipe;
1159 ServerSendAfterClose server(std::move(pipe.handle0));
[email protected]87339f02010-09-02 21:45:501160 server.Start();
1161
1162 server.done_event()->Wait();
1163 server.done_event()->Reset();
1164
1165 server.SendDummy();
1166 server.done_event()->Wait();
1167
1168 EXPECT_FALSE(server.send_result());
[email protected]bf2a9092013-01-08 06:09:071169
1170 server.Shutdown();
[email protected]87339f02010-09-02 21:45:501171}
1172
[email protected]2a3aa7b52013-01-11 20:56:221173//------------------------------------------------------------------------------
[email protected]54af05f2011-04-08 03:38:211174
1175class RestrictedDispatchServer : public Worker {
1176 public:
[email protected]298ee7d2012-03-30 21:29:301177 RestrictedDispatchServer(WaitableEvent* sent_ping_event,
sammc4bcc4ed62016-10-27 10:13:591178 WaitableEvent* wait_event,
1179 mojo::ScopedMessagePipeHandle channel_handle)
1180 : Worker(std::move(channel_handle), Channel::MODE_SERVER),
[email protected]298ee7d2012-03-30 21:29:301181 sent_ping_event_(sent_ping_event),
sammc4bcc4ed62016-10-27 10:13:591182 wait_event_(wait_event) {}
[email protected]54af05f2011-04-08 03:38:211183
1184 void OnDoPing(int ping) {
1185 // Send an asynchronous message that unblocks the caller.
[email protected]c9e0c7332011-05-13 22:42:411186 Message* msg = new SyncChannelTestMsg_Ping(ping);
[email protected]54af05f2011-04-08 03:38:211187 msg->set_unblock(true);
1188 Send(msg);
1189 // Signal the event after the message has been sent on the channel, on the
1190 // IPC thread.
skyostile687bdff2015-05-12 11:29:211191 ipc_thread().task_runner()->PostTask(
tzik9805c862017-07-06 00:15:511192 FROM_HERE, base::Bind(&RestrictedDispatchServer::OnPingSent,
1193 base::Unretained(this)));
[email protected]54af05f2011-04-08 03:38:211194 }
1195
[email protected]298ee7d2012-03-30 21:29:301196 void OnPingTTL(int ping, int* out) {
1197 *out = ping;
1198 wait_event_->Wait();
1199 }
1200
[email protected]54af05f2011-04-08 03:38:211201 base::Thread* ListenerThread() { return Worker::ListenerThread(); }
1202
1203 private:
dchengfe61fca2014-10-22 02:29:521204 bool OnMessageReceived(const Message& message) override {
[email protected]54af05f2011-04-08 03:38:211205 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchServer, message)
1206 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
[email protected]298ee7d2012-03-30 21:29:301207 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_PingTTL, OnPingTTL)
[email protected]54af05f2011-04-08 03:38:211208 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
1209 IPC_END_MESSAGE_MAP()
1210 return true;
1211 }
1212
1213 void OnPingSent() {
1214 sent_ping_event_->Signal();
1215 }
1216
1217 void OnNoArgs() { }
1218 WaitableEvent* sent_ping_event_;
[email protected]298ee7d2012-03-30 21:29:301219 WaitableEvent* wait_event_;
[email protected]54af05f2011-04-08 03:38:211220};
1221
1222class NonRestrictedDispatchServer : public Worker {
1223 public:
sammc4bcc4ed62016-10-27 10:13:591224 NonRestrictedDispatchServer(WaitableEvent* signal_event,
1225 mojo::ScopedMessagePipeHandle channel_handle)
1226 : Worker(std::move(channel_handle), Channel::MODE_SERVER),
[email protected]298ee7d2012-03-30 21:29:301227 signal_event_(signal_event) {}
1228
1229 base::Thread* ListenerThread() { return Worker::ListenerThread(); }
1230
1231 void OnDoPingTTL(int ping) {
1232 int value = 0;
1233 Send(new SyncChannelTestMsg_PingTTL(ping, &value));
1234 signal_event_->Signal();
1235 }
[email protected]54af05f2011-04-08 03:38:211236
1237 private:
dchengfe61fca2014-10-22 02:29:521238 bool OnMessageReceived(const Message& message) override {
[email protected]54af05f2011-04-08 03:38:211239 IPC_BEGIN_MESSAGE_MAP(NonRestrictedDispatchServer, message)
1240 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1241 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
1242 IPC_END_MESSAGE_MAP()
1243 return true;
1244 }
1245
1246 void OnNoArgs() { }
[email protected]298ee7d2012-03-30 21:29:301247 WaitableEvent* signal_event_;
[email protected]54af05f2011-04-08 03:38:211248};
1249
1250class RestrictedDispatchClient : public Worker {
1251 public:
sammc4bcc4ed62016-10-27 10:13:591252 RestrictedDispatchClient(
1253 WaitableEvent* sent_ping_event,
1254 RestrictedDispatchServer* server,
1255 NonRestrictedDispatchServer* server2,
1256 int* success,
1257 mojo::ScopedMessagePipeHandle restricted_channel_handle,
1258 mojo::ScopedMessagePipeHandle non_restricted_channel_handle)
1259 : Worker(std::move(restricted_channel_handle), Channel::MODE_CLIENT),
[email protected]54af05f2011-04-08 03:38:211260 ping_(0),
1261 server_(server),
[email protected]298ee7d2012-03-30 21:29:301262 server2_(server2),
[email protected]54af05f2011-04-08 03:38:211263 success_(success),
sammc4bcc4ed62016-10-27 10:13:591264 sent_ping_event_(sent_ping_event),
1265 non_restricted_channel_handle_(
1266 std::move(non_restricted_channel_handle)) {}
[email protected]54af05f2011-04-08 03:38:211267
dchengfe61fca2014-10-22 02:29:521268 void Run() override {
[email protected]54af05f2011-04-08 03:38:211269 // Incoming messages from our channel should only be dispatched when we
1270 // send a message on that same channel.
[email protected]298ee7d2012-03-30 21:29:301271 channel()->SetRestrictDispatchChannelGroup(1);
[email protected]54af05f2011-04-08 03:38:211272
skyostile687bdff2015-05-12 11:29:211273 server_->ListenerThread()->task_runner()->PostTask(
tzik9805c862017-07-06 00:15:511274 FROM_HERE, base::Bind(&RestrictedDispatchServer::OnDoPing,
1275 base::Unretained(server_), 1));
[email protected]54af05f2011-04-08 03:38:211276 sent_ping_event_->Wait();
1277 Send(new SyncChannelTestMsg_NoArgs);
1278 if (ping_ == 1)
1279 ++*success_;
1280 else
1281 LOG(ERROR) << "Send failed to dispatch incoming message on same channel";
1282
skyostile687bdff2015-05-12 11:29:211283 non_restricted_channel_ = SyncChannel::Create(
sammc4bcc4ed62016-10-27 10:13:591284 non_restricted_channel_handle_.release(), IPC::Channel::MODE_CLIENT,
Hajime Hoshiff15e972017-11-09 06:37:091285 this, ipc_thread().task_runner(), base::ThreadTaskRunnerHandle::Get(),
1286 true, shutdown_event());
[email protected]54af05f2011-04-08 03:38:211287
skyostile687bdff2015-05-12 11:29:211288 server_->ListenerThread()->task_runner()->PostTask(
tzik9805c862017-07-06 00:15:511289 FROM_HERE, base::Bind(&RestrictedDispatchServer::OnDoPing,
1290 base::Unretained(server_), 2));
[email protected]54af05f2011-04-08 03:38:211291 sent_ping_event_->Wait();
1292 // Check that the incoming message is *not* dispatched when sending on the
1293 // non restricted channel.
1294 // TODO(piman): there is a possibility of a false positive race condition
1295 // here, if the message that was posted on the server-side end of the pipe
1296 // is not visible yet on the client side, but I don't know how to solve this
1297 // without hooking into the internals of SyncChannel. I haven't seen it in
1298 // practice (i.e. not setting SetRestrictDispatchToSameChannel does cause
1299 // the following to fail).
[email protected]298ee7d2012-03-30 21:29:301300 non_restricted_channel_->Send(new SyncChannelTestMsg_NoArgs);
[email protected]54af05f2011-04-08 03:38:211301 if (ping_ == 1)
1302 ++*success_;
1303 else
1304 LOG(ERROR) << "Send dispatched message from restricted channel";
1305
1306 Send(new SyncChannelTestMsg_NoArgs);
1307 if (ping_ == 2)
1308 ++*success_;
1309 else
1310 LOG(ERROR) << "Send failed to dispatch incoming message on same channel";
1311
[email protected]298ee7d2012-03-30 21:29:301312 // Check that the incoming message on the non-restricted channel is
1313 // dispatched when sending on the restricted channel.
skyostile687bdff2015-05-12 11:29:211314 server2_->ListenerThread()->task_runner()->PostTask(
tzik9805c862017-07-06 00:15:511315 FROM_HERE, base::Bind(&NonRestrictedDispatchServer::OnDoPingTTL,
1316 base::Unretained(server2_), 3));
[email protected]298ee7d2012-03-30 21:29:301317 int value = 0;
1318 Send(new SyncChannelTestMsg_PingTTL(4, &value));
1319 if (ping_ == 3 && value == 4)
1320 ++*success_;
1321 else
1322 LOG(ERROR) << "Send failed to dispatch message from unrestricted channel";
1323
1324 non_restricted_channel_->Send(new SyncChannelTestMsg_Done);
1325 non_restricted_channel_.reset();
[email protected]54af05f2011-04-08 03:38:211326 Send(new SyncChannelTestMsg_Done);
1327 Done();
1328 }
1329
1330 private:
dchengfe61fca2014-10-22 02:29:521331 bool OnMessageReceived(const Message& message) override {
[email protected]54af05f2011-04-08 03:38:211332 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchClient, message)
1333 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Ping, OnPing)
[email protected]298ee7d2012-03-30 21:29:301334 IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncChannelTestMsg_PingTTL, OnPingTTL)
[email protected]54af05f2011-04-08 03:38:211335 IPC_END_MESSAGE_MAP()
1336 return true;
1337 }
1338
1339 void OnPing(int ping) {
1340 ping_ = ping;
1341 }
1342
[email protected]298ee7d2012-03-30 21:29:301343 void OnPingTTL(int ping, IPC::Message* reply) {
1344 ping_ = ping;
1345 // This message comes from the NonRestrictedDispatchServer, we have to send
1346 // the reply back manually.
1347 SyncChannelTestMsg_PingTTL::WriteReplyParams(reply, ping);
1348 non_restricted_channel_->Send(reply);
1349 }
1350
[email protected]54af05f2011-04-08 03:38:211351 int ping_;
1352 RestrictedDispatchServer* server_;
[email protected]298ee7d2012-03-30 21:29:301353 NonRestrictedDispatchServer* server2_;
[email protected]54af05f2011-04-08 03:38:211354 int* success_;
1355 WaitableEvent* sent_ping_event_;
danakj03de39b22016-04-23 04:21:091356 std::unique_ptr<SyncChannel> non_restricted_channel_;
sammc4bcc4ed62016-10-27 10:13:591357 mojo::ScopedMessagePipeHandle non_restricted_channel_handle_;
[email protected]54af05f2011-04-08 03:38:211358};
1359
[email protected]54af05f2011-04-08 03:38:211360TEST_F(IPCSyncChannelTest, RestrictedDispatch) {
gab90c2c5c2016-06-01 20:34:061361 WaitableEvent sent_ping_event(
1362 base::WaitableEvent::ResetPolicy::AUTOMATIC,
1363 base::WaitableEvent::InitialState::NOT_SIGNALED);
1364 WaitableEvent wait_event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1365 base::WaitableEvent::InitialState::NOT_SIGNALED);
sammc4bcc4ed62016-10-27 10:13:591366 mojo::MessagePipe restricted_pipe, non_restricted_pipe;
1367 RestrictedDispatchServer* server = new RestrictedDispatchServer(
1368 &sent_ping_event, &wait_event, std::move(restricted_pipe.handle0));
1369 NonRestrictedDispatchServer* server2 = new NonRestrictedDispatchServer(
1370 &wait_event, std::move(non_restricted_pipe.handle0));
[email protected]298ee7d2012-03-30 21:29:301371
[email protected]54af05f2011-04-08 03:38:211372 int success = 0;
1373 std::vector<Worker*> workers;
[email protected]54af05f2011-04-08 03:38:211374 workers.push_back(server);
[email protected]298ee7d2012-03-30 21:29:301375 workers.push_back(server2);
sammc4bcc4ed62016-10-27 10:13:591376 workers.push_back(
1377 new RestrictedDispatchClient(&sent_ping_event, server, server2, &success,
1378 std::move(restricted_pipe.handle1),
1379 std::move(non_restricted_pipe.handle1)));
[email protected]54af05f2011-04-08 03:38:211380 RunTest(workers);
[email protected]298ee7d2012-03-30 21:29:301381 EXPECT_EQ(4, success);
[email protected]54af05f2011-04-08 03:38:211382}
[email protected]c9e0c7332011-05-13 22:42:411383
[email protected]2a3aa7b52013-01-11 20:56:221384//------------------------------------------------------------------------------
[email protected]522cc10d2012-01-11 22:39:541385
1386// This test case inspired by crbug.com/108491
1387// We create two servers that use the same ListenerThread but have
1388// SetRestrictDispatchToSameChannel set to true.
1389// We create clients, then use some specific WaitableEvent wait/signalling to
1390// ensure that messages get dispatched in a way that causes a deadlock due to
1391// a nested dispatch and an eligible message in a higher-level dispatch's
1392// delayed_queue. Specifically, we start with client1 about so send an
1393// unblocking message to server1, while the shared listener thread for the
1394// servers server1 and server2 is about to send a non-unblocking message to
1395// client1. At the same time, client2 will be about to send an unblocking
1396// message to server2. Server1 will handle the client1->server1 message by
1397// telling server2 to send a non-unblocking message to client2.
1398// What should happen is that the send to server2 should find the pending,
1399// same-context client2->server2 message to dispatch, causing client2 to
1400// unblock then handle the server2->client2 message, so that the shared
1401// servers' listener thread can then respond to the client1->server1 message.
1402// Then client1 can handle the non-unblocking server1->client1 message.
1403// The old code would end up in a state where the server2->client2 message is
1404// sent, but the client2->server2 message (which is eligible for dispatch, and
1405// which is what client2 is waiting for) is stashed in a local delayed_queue
1406// that has server1's channel context, causing a deadlock.
1407// WaitableEvents in the events array are used to:
1408// event 0: indicate to client1 that server listener is in OnDoServerTask
1409// event 1: indicate to client1 that client2 listener is in OnDoClient2Task
1410// event 2: indicate to server1 that client2 listener is in OnDoClient2Task
1411// event 3: indicate to client2 that server listener is in OnDoServerTask
1412
[email protected]522cc10d2012-01-11 22:39:541413class RestrictedDispatchDeadlockServer : public Worker {
1414 public:
1415 RestrictedDispatchDeadlockServer(int server_num,
1416 WaitableEvent* server_ready_event,
1417 WaitableEvent** events,
sammc4bcc4ed62016-10-27 10:13:591418 RestrictedDispatchDeadlockServer* peer,
1419 mojo::ScopedMessagePipeHandle channel_handle)
1420 : Worker(std::move(channel_handle), Channel::MODE_SERVER),
[email protected]522cc10d2012-01-11 22:39:541421 server_num_(server_num),
1422 server_ready_event_(server_ready_event),
1423 events_(events),
sammc4bcc4ed62016-10-27 10:13:591424 peer_(peer) {}
[email protected]522cc10d2012-01-11 22:39:541425
1426 void OnDoServerTask() {
1427 events_[3]->Signal();
1428 events_[2]->Wait();
1429 events_[0]->Signal();
1430 SendMessageToClient();
1431 }
1432
dchengfe61fca2014-10-22 02:29:521433 void Run() override {
[email protected]298ee7d2012-03-30 21:29:301434 channel()->SetRestrictDispatchChannelGroup(1);
[email protected]522cc10d2012-01-11 22:39:541435 server_ready_event_->Signal();
1436 }
1437
1438 base::Thread* ListenerThread() { return Worker::ListenerThread(); }
1439
1440 private:
dchengfe61fca2014-10-22 02:29:521441 bool OnMessageReceived(const Message& message) override {
[email protected]522cc10d2012-01-11 22:39:541442 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockServer, message)
1443 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1444 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, Done)
1445 IPC_END_MESSAGE_MAP()
1446 return true;
1447 }
1448
1449 void OnNoArgs() {
1450 if (server_num_ == 1) {
1451 DCHECK(peer_ != NULL);
1452 peer_->SendMessageToClient();
1453 }
1454 }
1455
1456 void SendMessageToClient() {
1457 Message* msg = new SyncChannelTestMsg_NoArgs;
1458 msg->set_unblock(false);
1459 DCHECK(!msg->should_unblock());
1460 Send(msg);
1461 }
1462
1463 int server_num_;
1464 WaitableEvent* server_ready_event_;
1465 WaitableEvent** events_;
1466 RestrictedDispatchDeadlockServer* peer_;
[email protected]522cc10d2012-01-11 22:39:541467};
1468
1469class RestrictedDispatchDeadlockClient2 : public Worker {
1470 public:
sammc4bcc4ed62016-10-27 10:13:591471 RestrictedDispatchDeadlockClient2(
1472 RestrictedDispatchDeadlockServer* server,
1473 WaitableEvent* server_ready_event,
1474 WaitableEvent** events,
1475 mojo::ScopedMessagePipeHandle channel_handle)
1476 : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
[email protected]522cc10d2012-01-11 22:39:541477 server_ready_event_(server_ready_event),
1478 events_(events),
1479 received_msg_(false),
1480 received_noarg_reply_(false),
1481 done_issued_(false) {}
1482
dchengfe61fca2014-10-22 02:29:521483 void Run() override {
dchengf3076af2014-10-21 18:02:421484 server_ready_event_->Wait();
1485 }
[email protected]522cc10d2012-01-11 22:39:541486
1487 void OnDoClient2Task() {
1488 events_[3]->Wait();
1489 events_[1]->Signal();
1490 events_[2]->Signal();
1491 DCHECK(received_msg_ == false);
1492
1493 Message* message = new SyncChannelTestMsg_NoArgs;
1494 message->set_unblock(true);
1495 Send(message);
1496 received_noarg_reply_ = true;
1497 }
1498
1499 base::Thread* ListenerThread() { return Worker::ListenerThread(); }
1500 private:
dchengfe61fca2014-10-22 02:29:521501 bool OnMessageReceived(const Message& message) override {
[email protected]522cc10d2012-01-11 22:39:541502 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockClient2, message)
1503 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1504 IPC_END_MESSAGE_MAP()
1505 return true;
1506 }
1507
1508 void OnNoArgs() {
1509 received_msg_ = true;
1510 PossiblyDone();
1511 }
1512
1513 void PossiblyDone() {
1514 if (received_noarg_reply_ && received_msg_) {
1515 DCHECK(done_issued_ == false);
1516 done_issued_ = true;
1517 Send(new SyncChannelTestMsg_Done);
1518 Done();
1519 }
1520 }
1521
[email protected]522cc10d2012-01-11 22:39:541522 WaitableEvent* server_ready_event_;
1523 WaitableEvent** events_;
1524 bool received_msg_;
1525 bool received_noarg_reply_;
1526 bool done_issued_;
1527};
1528
1529class RestrictedDispatchDeadlockClient1 : public Worker {
1530 public:
sammc4bcc4ed62016-10-27 10:13:591531 RestrictedDispatchDeadlockClient1(
1532 RestrictedDispatchDeadlockServer* server,
1533 RestrictedDispatchDeadlockClient2* peer,
1534 WaitableEvent* server_ready_event,
1535 WaitableEvent** events,
1536 mojo::ScopedMessagePipeHandle channel_handle)
1537 : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
[email protected]522cc10d2012-01-11 22:39:541538 server_(server),
1539 peer_(peer),
1540 server_ready_event_(server_ready_event),
1541 events_(events),
1542 received_msg_(false),
1543 received_noarg_reply_(false),
1544 done_issued_(false) {}
1545
dchengfe61fca2014-10-22 02:29:521546 void Run() override {
[email protected]522cc10d2012-01-11 22:39:541547 server_ready_event_->Wait();
skyostile687bdff2015-05-12 11:29:211548 server_->ListenerThread()->task_runner()->PostTask(
tzik9805c862017-07-06 00:15:511549 FROM_HERE, base::Bind(&RestrictedDispatchDeadlockServer::OnDoServerTask,
1550 base::Unretained(server_)));
skyostile687bdff2015-05-12 11:29:211551 peer_->ListenerThread()->task_runner()->PostTask(
[email protected]522cc10d2012-01-11 22:39:541552 FROM_HERE,
tzik9805c862017-07-06 00:15:511553 base::Bind(&RestrictedDispatchDeadlockClient2::OnDoClient2Task,
1554 base::Unretained(peer_)));
[email protected]522cc10d2012-01-11 22:39:541555 events_[0]->Wait();
1556 events_[1]->Wait();
1557 DCHECK(received_msg_ == false);
1558
1559 Message* message = new SyncChannelTestMsg_NoArgs;
1560 message->set_unblock(true);
1561 Send(message);
1562 received_noarg_reply_ = true;
1563 PossiblyDone();
1564 }
1565
[email protected]522cc10d2012-01-11 22:39:541566 private:
dchengfe61fca2014-10-22 02:29:521567 bool OnMessageReceived(const Message& message) override {
[email protected]522cc10d2012-01-11 22:39:541568 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchDeadlockClient1, message)
1569 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_NoArgs, OnNoArgs)
1570 IPC_END_MESSAGE_MAP()
1571 return true;
1572 }
1573
1574 void OnNoArgs() {
1575 received_msg_ = true;
1576 PossiblyDone();
1577 }
1578
1579 void PossiblyDone() {
1580 if (received_noarg_reply_ && received_msg_) {
1581 DCHECK(done_issued_ == false);
1582 done_issued_ = true;
1583 Send(new SyncChannelTestMsg_Done);
1584 Done();
1585 }
1586 }
1587
1588 RestrictedDispatchDeadlockServer* server_;
1589 RestrictedDispatchDeadlockClient2* peer_;
1590 WaitableEvent* server_ready_event_;
1591 WaitableEvent** events_;
1592 bool received_msg_;
1593 bool received_noarg_reply_;
1594 bool done_issued_;
1595};
1596
[email protected]522cc10d2012-01-11 22:39:541597TEST_F(IPCSyncChannelTest, RestrictedDispatchDeadlock) {
1598 std::vector<Worker*> workers;
1599
1600 // A shared worker thread so that server1 and server2 run on one thread.
1601 base::Thread worker_thread("RestrictedDispatchDeadlock");
1602 ASSERT_TRUE(worker_thread.Start());
1603
gab90c2c5c2016-06-01 20:34:061604 WaitableEvent server1_ready(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1605 base::WaitableEvent::InitialState::NOT_SIGNALED);
1606 WaitableEvent server2_ready(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1607 base::WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]522cc10d2012-01-11 22:39:541608
gab90c2c5c2016-06-01 20:34:061609 WaitableEvent event0(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1610 base::WaitableEvent::InitialState::NOT_SIGNALED);
1611 WaitableEvent event1(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1612 base::WaitableEvent::InitialState::NOT_SIGNALED);
1613 WaitableEvent event2(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1614 base::WaitableEvent::InitialState::NOT_SIGNALED);
1615 WaitableEvent event3(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1616 base::WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]522cc10d2012-01-11 22:39:541617 WaitableEvent* events[4] = {&event0, &event1, &event2, &event3};
1618
1619 RestrictedDispatchDeadlockServer* server1;
1620 RestrictedDispatchDeadlockServer* server2;
1621 RestrictedDispatchDeadlockClient1* client1;
1622 RestrictedDispatchDeadlockClient2* client2;
1623
sammc4bcc4ed62016-10-27 10:13:591624 mojo::MessagePipe pipe1, pipe2;
1625 server2 = new RestrictedDispatchDeadlockServer(
1626 2, &server2_ready, events, NULL, std::move(pipe2.handle0));
[email protected]522cc10d2012-01-11 22:39:541627 server2->OverrideThread(&worker_thread);
1628 workers.push_back(server2);
1629
sammc4bcc4ed62016-10-27 10:13:591630 client2 = new RestrictedDispatchDeadlockClient2(
1631 server2, &server2_ready, events, std::move(pipe2.handle1));
[email protected]522cc10d2012-01-11 22:39:541632 workers.push_back(client2);
1633
sammc4bcc4ed62016-10-27 10:13:591634 server1 = new RestrictedDispatchDeadlockServer(
1635 1, &server1_ready, events, server2, std::move(pipe1.handle0));
[email protected]522cc10d2012-01-11 22:39:541636 server1->OverrideThread(&worker_thread);
1637 workers.push_back(server1);
1638
sammc4bcc4ed62016-10-27 10:13:591639 client1 = new RestrictedDispatchDeadlockClient1(
1640 server1, client2, &server1_ready, events, std::move(pipe1.handle1));
[email protected]522cc10d2012-01-11 22:39:541641 workers.push_back(client1);
1642
1643 RunTest(workers);
1644}
1645
[email protected]2a3aa7b52013-01-11 20:56:221646//------------------------------------------------------------------------------
[email protected]5c41e6e12012-03-17 02:20:461647
[email protected]298ee7d2012-03-30 21:29:301648// This test case inspired by crbug.com/120530
1649// We create 4 workers that pipe to each other W1->W2->W3->W4->W1 then we send a
1650// message that recurses through 3, 4 or 5 steps to make sure, say, W1 can
1651// re-enter when called from W4 while it's sending a message to W2.
1652// The first worker drives the whole test so it must be treated specially.
[email protected]298ee7d2012-03-30 21:29:301653
1654class RestrictedDispatchPipeWorker : public Worker {
1655 public:
sammc4bcc4ed62016-10-27 10:13:591656 RestrictedDispatchPipeWorker(mojo::ScopedMessagePipeHandle channel_handle1,
1657 WaitableEvent* event1,
1658 mojo::ScopedMessagePipeHandle channel_handle2,
1659 WaitableEvent* event2,
1660 int group,
1661 int* success)
1662 : Worker(std::move(channel_handle1), Channel::MODE_SERVER),
[email protected]298ee7d2012-03-30 21:29:301663 event1_(event1),
1664 event2_(event2),
sammc4bcc4ed62016-10-27 10:13:591665 other_channel_handle_(std::move(channel_handle2)),
[email protected]298ee7d2012-03-30 21:29:301666 group_(group),
sammc4bcc4ed62016-10-27 10:13:591667 success_(success) {}
[email protected]298ee7d2012-03-30 21:29:301668
1669 void OnPingTTL(int ping, int* ret) {
1670 *ret = 0;
1671 if (!ping)
1672 return;
1673 other_channel_->Send(new SyncChannelTestMsg_PingTTL(ping - 1, ret));
1674 ++*ret;
1675 }
1676
1677 void OnDone() {
1678 if (is_first())
1679 return;
1680 other_channel_->Send(new SyncChannelTestMsg_Done);
1681 other_channel_.reset();
1682 Done();
1683 }
1684
dchengfe61fca2014-10-22 02:29:521685 void Run() override {
[email protected]298ee7d2012-03-30 21:29:301686 channel()->SetRestrictDispatchChannelGroup(group_);
1687 if (is_first())
1688 event1_->Signal();
1689 event2_->Wait();
skyostile687bdff2015-05-12 11:29:211690 other_channel_ = SyncChannel::Create(
sammc4bcc4ed62016-10-27 10:13:591691 other_channel_handle_.release(), IPC::Channel::MODE_CLIENT, this,
Hajime Hoshiff15e972017-11-09 06:37:091692 ipc_thread().task_runner(), base::ThreadTaskRunnerHandle::Get(), true,
1693 shutdown_event());
[email protected]298ee7d2012-03-30 21:29:301694 other_channel_->SetRestrictDispatchChannelGroup(group_);
1695 if (!is_first()) {
1696 event1_->Signal();
1697 return;
1698 }
1699 *success_ = 0;
1700 int value = 0;
1701 OnPingTTL(3, &value);
1702 *success_ += (value == 3);
1703 OnPingTTL(4, &value);
1704 *success_ += (value == 4);
1705 OnPingTTL(5, &value);
1706 *success_ += (value == 5);
1707 other_channel_->Send(new SyncChannelTestMsg_Done);
1708 other_channel_.reset();
1709 Done();
1710 }
1711
1712 bool is_first() { return !!success_; }
1713
1714 private:
dchengfe61fca2014-10-22 02:29:521715 bool OnMessageReceived(const Message& message) override {
[email protected]298ee7d2012-03-30 21:29:301716 IPC_BEGIN_MESSAGE_MAP(RestrictedDispatchPipeWorker, message)
1717 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_PingTTL, OnPingTTL)
1718 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Done, OnDone)
1719 IPC_END_MESSAGE_MAP()
1720 return true;
1721 }
1722
danakj03de39b22016-04-23 04:21:091723 std::unique_ptr<SyncChannel> other_channel_;
[email protected]298ee7d2012-03-30 21:29:301724 WaitableEvent* event1_;
1725 WaitableEvent* event2_;
sammc4bcc4ed62016-10-27 10:13:591726 mojo::ScopedMessagePipeHandle other_channel_handle_;
[email protected]298ee7d2012-03-30 21:29:301727 int group_;
1728 int* success_;
1729};
1730
tfarina8514f0d2015-07-28 14:41:471731#if defined(OS_ANDROID)
1732#define MAYBE_RestrictedDispatch4WayDeadlock \
1733 DISABLED_RestrictedDispatch4WayDeadlock
1734#else
1735#define MAYBE_RestrictedDispatch4WayDeadlock RestrictedDispatch4WayDeadlock
1736#endif
1737TEST_F(IPCSyncChannelTest, MAYBE_RestrictedDispatch4WayDeadlock) {
[email protected]298ee7d2012-03-30 21:29:301738 int success = 0;
1739 std::vector<Worker*> workers;
gab90c2c5c2016-06-01 20:34:061740 WaitableEvent event0(base::WaitableEvent::ResetPolicy::MANUAL,
1741 base::WaitableEvent::InitialState::NOT_SIGNALED);
1742 WaitableEvent event1(base::WaitableEvent::ResetPolicy::MANUAL,
1743 base::WaitableEvent::InitialState::NOT_SIGNALED);
1744 WaitableEvent event2(base::WaitableEvent::ResetPolicy::MANUAL,
1745 base::WaitableEvent::InitialState::NOT_SIGNALED);
1746 WaitableEvent event3(base::WaitableEvent::ResetPolicy::MANUAL,
1747 base::WaitableEvent::InitialState::NOT_SIGNALED);
sammc4bcc4ed62016-10-27 10:13:591748 mojo::MessagePipe pipe0, pipe1, pipe2, pipe3;
[email protected]298ee7d2012-03-30 21:29:301749 workers.push_back(new RestrictedDispatchPipeWorker(
sammc4bcc4ed62016-10-27 10:13:591750 std::move(pipe0.handle0), &event0, std::move(pipe1.handle1), &event1, 1,
1751 &success));
[email protected]298ee7d2012-03-30 21:29:301752 workers.push_back(new RestrictedDispatchPipeWorker(
sammc4bcc4ed62016-10-27 10:13:591753 std::move(pipe1.handle0), &event1, std::move(pipe2.handle1), &event2, 2,
1754 NULL));
[email protected]298ee7d2012-03-30 21:29:301755 workers.push_back(new RestrictedDispatchPipeWorker(
sammc4bcc4ed62016-10-27 10:13:591756 std::move(pipe2.handle0), &event2, std::move(pipe3.handle1), &event3, 3,
1757 NULL));
[email protected]298ee7d2012-03-30 21:29:301758 workers.push_back(new RestrictedDispatchPipeWorker(
sammc4bcc4ed62016-10-27 10:13:591759 std::move(pipe3.handle0), &event3, std::move(pipe0.handle1), &event0, 4,
1760 NULL));
[email protected]298ee7d2012-03-30 21:29:301761 RunTest(workers);
1762 EXPECT_EQ(3, success);
1763}
1764
[email protected]2a3aa7b52013-01-11 20:56:221765//------------------------------------------------------------------------------
[email protected]9134cce6d2012-04-10 20:07:531766
[email protected]9134cce6d2012-04-10 20:07:531767// This test case inspired by crbug.com/122443
1768// We want to make sure a reply message with the unblock flag set correctly
1769// behaves as a reply, not a regular message.
1770// We have 3 workers. Server1 will send a message to Server2 (which will block),
1771// during which it will dispatch a message comming from Client, at which point
1772// it will send another message to Server2. While sending that second message it
1773// will receive a reply from Server1 with the unblock flag.
1774
[email protected]9134cce6d2012-04-10 20:07:531775class ReentrantReplyServer1 : public Worker {
1776 public:
sammc4bcc4ed62016-10-27 10:13:591777 ReentrantReplyServer1(WaitableEvent* server_ready,
1778 mojo::ScopedMessagePipeHandle channel_handle1,
1779 mojo::ScopedMessagePipeHandle channel_handle2)
1780 : Worker(std::move(channel_handle1), Channel::MODE_SERVER),
1781 server_ready_(server_ready),
1782 other_channel_handle_(std::move(channel_handle2)) {}
[email protected]9134cce6d2012-04-10 20:07:531783
dchengfe61fca2014-10-22 02:29:521784 void Run() override {
skyostile687bdff2015-05-12 11:29:211785 server2_channel_ = SyncChannel::Create(
sammc4bcc4ed62016-10-27 10:13:591786 other_channel_handle_.release(), IPC::Channel::MODE_CLIENT, this,
Hajime Hoshiff15e972017-11-09 06:37:091787 ipc_thread().task_runner(), base::ThreadTaskRunnerHandle::Get(), true,
1788 shutdown_event());
[email protected]9134cce6d2012-04-10 20:07:531789 server_ready_->Signal();
1790 Message* msg = new SyncChannelTestMsg_Reentrant1();
1791 server2_channel_->Send(msg);
1792 server2_channel_.reset();
1793 Done();
1794 }
1795
1796 private:
dchengfe61fca2014-10-22 02:29:521797 bool OnMessageReceived(const Message& message) override {
[email protected]9134cce6d2012-04-10 20:07:531798 IPC_BEGIN_MESSAGE_MAP(ReentrantReplyServer1, message)
1799 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Reentrant2, OnReentrant2)
1800 IPC_REPLY_HANDLER(OnReply)
1801 IPC_END_MESSAGE_MAP()
1802 return true;
1803 }
1804
1805 void OnReentrant2() {
1806 Message* msg = new SyncChannelTestMsg_Reentrant3();
1807 server2_channel_->Send(msg);
1808 }
1809
1810 void OnReply(const Message& message) {
1811 // If we get here, the Send() will never receive the reply (thus would
1812 // hang), so abort instead.
1813 LOG(FATAL) << "Reply message was dispatched";
1814 }
1815
1816 WaitableEvent* server_ready_;
danakj03de39b22016-04-23 04:21:091817 std::unique_ptr<SyncChannel> server2_channel_;
sammc4bcc4ed62016-10-27 10:13:591818 mojo::ScopedMessagePipeHandle other_channel_handle_;
[email protected]9134cce6d2012-04-10 20:07:531819};
1820
1821class ReentrantReplyServer2 : public Worker {
1822 public:
sammc4bcc4ed62016-10-27 10:13:591823 ReentrantReplyServer2(mojo::ScopedMessagePipeHandle channel_handle)
1824 : Worker(std::move(channel_handle), Channel::MODE_SERVER), reply_(NULL) {}
[email protected]9134cce6d2012-04-10 20:07:531825
1826 private:
dchengfe61fca2014-10-22 02:29:521827 bool OnMessageReceived(const Message& message) override {
[email protected]9134cce6d2012-04-10 20:07:531828 IPC_BEGIN_MESSAGE_MAP(ReentrantReplyServer2, message)
1829 IPC_MESSAGE_HANDLER_DELAY_REPLY(
1830 SyncChannelTestMsg_Reentrant1, OnReentrant1)
1831 IPC_MESSAGE_HANDLER(SyncChannelTestMsg_Reentrant3, OnReentrant3)
1832 IPC_END_MESSAGE_MAP()
1833 return true;
1834 }
1835
1836 void OnReentrant1(Message* reply) {
1837 DCHECK(!reply_);
1838 reply_ = reply;
1839 }
1840
1841 void OnReentrant3() {
1842 DCHECK(reply_);
1843 Message* reply = reply_;
1844 reply_ = NULL;
1845 reply->set_unblock(true);
1846 Send(reply);
1847 Done();
1848 }
1849
1850 Message* reply_;
1851};
1852
1853class ReentrantReplyClient : public Worker {
1854 public:
sammc4bcc4ed62016-10-27 10:13:591855 ReentrantReplyClient(WaitableEvent* server_ready,
1856 mojo::ScopedMessagePipeHandle channel_handle)
1857 : Worker(std::move(channel_handle), Channel::MODE_CLIENT),
1858 server_ready_(server_ready) {}
[email protected]9134cce6d2012-04-10 20:07:531859
dchengfe61fca2014-10-22 02:29:521860 void Run() override {
[email protected]9134cce6d2012-04-10 20:07:531861 server_ready_->Wait();
1862 Send(new SyncChannelTestMsg_Reentrant2());
1863 Done();
1864 }
1865
1866 private:
1867 WaitableEvent* server_ready_;
1868};
1869
[email protected]9134cce6d2012-04-10 20:07:531870TEST_F(IPCSyncChannelTest, ReentrantReply) {
1871 std::vector<Worker*> workers;
gab90c2c5c2016-06-01 20:34:061872 WaitableEvent server_ready(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1873 base::WaitableEvent::InitialState::NOT_SIGNALED);
sammc4bcc4ed62016-10-27 10:13:591874 mojo::MessagePipe pipe1, pipe2;
1875 workers.push_back(new ReentrantReplyServer2(std::move(pipe2.handle0)));
1876 workers.push_back(new ReentrantReplyServer1(
1877 &server_ready, std::move(pipe1.handle0), std::move(pipe2.handle1)));
1878 workers.push_back(
1879 new ReentrantReplyClient(&server_ready, std::move(pipe1.handle1)));
[email protected]9134cce6d2012-04-10 20:07:531880 RunTest(workers);
1881}
1882
[email protected]2a3aa7b52013-01-11 20:56:221883} // namespace
[email protected]2d6e6a72013-02-08 20:11:021884} // namespace IPC