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

Side by Side Diff: ipc/ipc_send_fds_test.cc

Issue 2473993003: Delete IPC::ChannelPosix, IPC::ChannelWin and IPC::AttachmentBroker. (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ipc/ipc_perftests.cc ('k') | ipc/ipc_test_base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "build/build_config.h" 5 #include "build/build_config.h"
6 6
7 #if defined(OS_POSIX) 7 #if defined(OS_POSIX)
8 #if defined(OS_MACOSX) 8 #if defined(OS_MACOSX)
9 extern "C" { 9 extern "C" {
10 #include <sandbox.h> 10 #include <sandbox.h>
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 206
207 // Make sure sandbox is really enabled. 207 // Make sure sandbox is really enabled.
208 ASSERT_EQ(-1, open(kDevZeroPath, O_RDONLY)) 208 ASSERT_EQ(-1, open(kDevZeroPath, O_RDONLY))
209 << "Sandbox wasn't properly enabled"; 209 << "Sandbox wasn't properly enabled";
210 210
211 // See if we can receive a file descriptor. 211 // See if we can receive a file descriptor.
212 SendFdsClientCommon("SendFdsSandboxedClient", st.st_ino); 212 SendFdsClientCommon("SendFdsSandboxedClient", st.st_ino);
213 } 213 }
214 #endif // defined(OS_MACOSX) 214 #endif // defined(OS_MACOSX)
215 215
216
217 class MyCBListener : public MyChannelDescriptorListenerBase {
218 public:
219 MyCBListener(base::Callback<void(int)> cb, int fds_to_send)
220 : MyChannelDescriptorListenerBase(),
221 cb_(cb) {
222 }
223
224 protected:
225 void HandleFD(int fd) override { cb_.Run(fd); }
226 private:
227 base::Callback<void(int)> cb_;
228 };
229
230 std::pair<int, int> make_socket_pair() {
231 int pipe_fds[2];
232 CHECK_EQ(0, HANDLE_EINTR(socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds)));
233 return std::pair<int, int>(pipe_fds[0], pipe_fds[1]);
234 }
235
236 static void null_cb(int unused_fd) {
237 NOTREACHED();
238 }
239
240 class PipeChannelHelper {
241 public:
242 PipeChannelHelper(base::Thread* in_thread,
243 base::Thread* out_thread,
244 base::Callback<void(int)> cb,
245 int fds_to_send) :
246 in_thread_(in_thread),
247 out_thread_(out_thread),
248 cb_listener_(cb, fds_to_send),
249 null_listener_(base::Bind(&null_cb), 0) {
250 }
251
252 void Init() {
253 IPC::ChannelHandle in_handle("IN");
254 in = IPC::Channel::CreateServer(
255 in_handle, &null_listener_, in_thread_->task_runner());
256 IPC::ChannelHandle out_handle(
257 "OUT", base::FileDescriptor(in->TakeClientFileDescriptor()));
258 out = IPC::Channel::CreateClient(
259 out_handle, &cb_listener_, out_thread_->task_runner());
260 // PostTask the connect calls to make sure the callbacks happens
261 // on the right threads.
262 in_thread_->task_runner()->PostTask(
263 FROM_HERE, base::Bind(&PipeChannelHelper::Connect, in.get()));
264 out_thread_->task_runner()->PostTask(
265 FROM_HERE, base::Bind(&PipeChannelHelper::Connect, out.get()));
266 }
267
268 static void DestroyChannel(std::unique_ptr<IPC::Channel>* c,
269 base::WaitableEvent* event) {
270 c->reset(0);
271 event->Signal();
272 }
273
274 ~PipeChannelHelper() {
275 base::WaitableEvent a(base::WaitableEvent::ResetPolicy::MANUAL,
276 base::WaitableEvent::InitialState::NOT_SIGNALED);
277 base::WaitableEvent b(base::WaitableEvent::ResetPolicy::MANUAL,
278 base::WaitableEvent::InitialState::NOT_SIGNALED);
279 in_thread_->task_runner()->PostTask(
280 FROM_HERE, base::Bind(&PipeChannelHelper::DestroyChannel, &in, &a));
281 out_thread_->task_runner()->PostTask(
282 FROM_HERE, base::Bind(&PipeChannelHelper::DestroyChannel, &out, &b));
283 a.Wait();
284 b.Wait();
285 }
286
287 static void Connect(IPC::Channel *channel) {
288 EXPECT_TRUE(channel->Connect());
289 }
290
291 void Send(int fd) {
292 CHECK_EQ(base::MessageLoop::current(), in_thread_->message_loop());
293
294 ASSERT_GE(fd, 0);
295 base::FileDescriptor descriptor(fd, true);
296
297 IPC::Message* message =
298 new IPC::Message(0, 3, IPC::Message::PRIORITY_NORMAL);
299 IPC::ParamTraits<base::FileDescriptor>::Write(message, descriptor);
300 ASSERT_TRUE(in->Send(message));
301 }
302
303 private:
304 std::unique_ptr<IPC::Channel> in, out;
305 base::Thread* in_thread_;
306 base::Thread* out_thread_;
307 MyCBListener cb_listener_;
308 MyCBListener null_listener_;
309 };
310
311 // This test is meant to provoke a kernel bug on OSX, and to prove
312 // that the workaround for it is working. It sets up two pipes and three
313 // threads, the producer thread creates socketpairs and sends one of the fds
314 // over pipe1 to the middleman thread. The middleman thread simply takes the fd
315 // sends it over pipe2 to the consumer thread. The consumer thread writes a byte
316 // to each fd it receives and then closes the pipe. The producer thread reads
317 // the bytes back from each pair of pipes and make sure that everything worked.
318 // This feedback mechanism makes sure that not too many file descriptors are
319 // in flight at the same time. For more info on the bug, see:
320 // http://crbug.com/298276
321 class IPCMultiSendingFdsTest : public testing::Test {
322 public:
323 IPCMultiSendingFdsTest()
324 : received_(base::WaitableEvent::ResetPolicy::MANUAL,
325 base::WaitableEvent::InitialState::NOT_SIGNALED) {}
326
327 void Producer(PipeChannelHelper* dest,
328 base::Thread* t,
329 int pipes_to_send) {
330 for (int i = 0; i < pipes_to_send; i++) {
331 received_.Reset();
332 std::pair<int, int> pipe_fds = make_socket_pair();
333 t->task_runner()->PostTask(
334 FROM_HERE, base::Bind(&PipeChannelHelper::Send,
335 base::Unretained(dest), pipe_fds.second));
336 char tmp = 'x';
337 CHECK_EQ(1, HANDLE_EINTR(write(pipe_fds.first, &tmp, 1)));
338 CHECK_EQ(0, IGNORE_EINTR(close(pipe_fds.first)));
339 received_.Wait();
340 }
341 }
342
343 void ConsumerHandleFD(int fd) {
344 char tmp = 'y';
345 CHECK_EQ(1, HANDLE_EINTR(read(fd, &tmp, 1)));
346 CHECK_EQ(tmp, 'x');
347 CHECK_EQ(0, IGNORE_EINTR(close(fd)));
348 received_.Signal();
349 }
350
351 base::Thread* CreateThread(const char* name) {
352 base::Thread* ret = new base::Thread(name);
353 base::Thread::Options options;
354 options.message_loop_type = base::MessageLoop::TYPE_IO;
355 ret->StartWithOptions(options);
356 return ret;
357 }
358
359 void Run() {
360 // On my mac, this test fails roughly 35 times per
361 // million sends with low load, but much more with high load.
362 // Unless the workaround is in place. With 10000 sends, we
363 // should see at least a 3% failure rate.
364 const int pipes_to_send = 20000;
365 std::unique_ptr<base::Thread> producer(CreateThread("producer"));
366 std::unique_ptr<base::Thread> middleman(CreateThread("middleman"));
367 std::unique_ptr<base::Thread> consumer(CreateThread("consumer"));
368 PipeChannelHelper pipe1(
369 middleman.get(),
370 consumer.get(),
371 base::Bind(&IPCMultiSendingFdsTest::ConsumerHandleFD,
372 base::Unretained(this)),
373 pipes_to_send);
374 PipeChannelHelper pipe2(
375 producer.get(),
376 middleman.get(),
377 base::Bind(&PipeChannelHelper::Send, base::Unretained(&pipe1)),
378 pipes_to_send);
379 pipe1.Init();
380 pipe2.Init();
381 Producer(&pipe2, producer.get(), pipes_to_send);
382 }
383
384 private:
385 base::WaitableEvent received_;
386 };
387
388 TEST_F(IPCMultiSendingFdsTest, StressTest) {
389 Run();
390 }
391
392 } // namespace 216 } // namespace
393 217
394 #endif // defined(OS_POSIX) 218 #endif // defined(OS_POSIX)
OLDNEW
« no previous file with comments | « ipc/ipc_perftests.cc ('k') | ipc/ipc_test_base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698