Index: ipc/ipc_send_fds_test.cc |
diff --git a/ipc/ipc_send_fds_test.cc b/ipc/ipc_send_fds_test.cc |
index 635b80a6365e124b5a53269fb5aaea10d34160ae..f648b6411ab27c9c6e150f700e89adb00949feb6 100644 |
--- a/ipc/ipc_send_fds_test.cc |
+++ b/ipc/ipc_send_fds_test.cc |
@@ -213,182 +213,6 @@ DEFINE_IPC_CHANNEL_MOJO_TEST_CLIENT_WITH_CUSTOM_FIXTURE( |
} |
#endif // defined(OS_MACOSX) |
- |
-class MyCBListener : public MyChannelDescriptorListenerBase { |
- public: |
- MyCBListener(base::Callback<void(int)> cb, int fds_to_send) |
- : MyChannelDescriptorListenerBase(), |
- cb_(cb) { |
- } |
- |
- protected: |
- void HandleFD(int fd) override { cb_.Run(fd); } |
- private: |
- base::Callback<void(int)> cb_; |
-}; |
- |
-std::pair<int, int> make_socket_pair() { |
- int pipe_fds[2]; |
- CHECK_EQ(0, HANDLE_EINTR(socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds))); |
- return std::pair<int, int>(pipe_fds[0], pipe_fds[1]); |
-} |
- |
-static void null_cb(int unused_fd) { |
- NOTREACHED(); |
-} |
- |
-class PipeChannelHelper { |
- public: |
- PipeChannelHelper(base::Thread* in_thread, |
- base::Thread* out_thread, |
- base::Callback<void(int)> cb, |
- int fds_to_send) : |
- in_thread_(in_thread), |
- out_thread_(out_thread), |
- cb_listener_(cb, fds_to_send), |
- null_listener_(base::Bind(&null_cb), 0) { |
- } |
- |
- void Init() { |
- IPC::ChannelHandle in_handle("IN"); |
- in = IPC::Channel::CreateServer( |
- in_handle, &null_listener_, in_thread_->task_runner()); |
- IPC::ChannelHandle out_handle( |
- "OUT", base::FileDescriptor(in->TakeClientFileDescriptor())); |
- out = IPC::Channel::CreateClient( |
- out_handle, &cb_listener_, out_thread_->task_runner()); |
- // PostTask the connect calls to make sure the callbacks happens |
- // on the right threads. |
- in_thread_->task_runner()->PostTask( |
- FROM_HERE, base::Bind(&PipeChannelHelper::Connect, in.get())); |
- out_thread_->task_runner()->PostTask( |
- FROM_HERE, base::Bind(&PipeChannelHelper::Connect, out.get())); |
- } |
- |
- static void DestroyChannel(std::unique_ptr<IPC::Channel>* c, |
- base::WaitableEvent* event) { |
- c->reset(0); |
- event->Signal(); |
- } |
- |
- ~PipeChannelHelper() { |
- base::WaitableEvent a(base::WaitableEvent::ResetPolicy::MANUAL, |
- base::WaitableEvent::InitialState::NOT_SIGNALED); |
- base::WaitableEvent b(base::WaitableEvent::ResetPolicy::MANUAL, |
- base::WaitableEvent::InitialState::NOT_SIGNALED); |
- in_thread_->task_runner()->PostTask( |
- FROM_HERE, base::Bind(&PipeChannelHelper::DestroyChannel, &in, &a)); |
- out_thread_->task_runner()->PostTask( |
- FROM_HERE, base::Bind(&PipeChannelHelper::DestroyChannel, &out, &b)); |
- a.Wait(); |
- b.Wait(); |
- } |
- |
- static void Connect(IPC::Channel *channel) { |
- EXPECT_TRUE(channel->Connect()); |
- } |
- |
- void Send(int fd) { |
- CHECK_EQ(base::MessageLoop::current(), in_thread_->message_loop()); |
- |
- ASSERT_GE(fd, 0); |
- base::FileDescriptor descriptor(fd, true); |
- |
- IPC::Message* message = |
- new IPC::Message(0, 3, IPC::Message::PRIORITY_NORMAL); |
- IPC::ParamTraits<base::FileDescriptor>::Write(message, descriptor); |
- ASSERT_TRUE(in->Send(message)); |
- } |
- |
- private: |
- std::unique_ptr<IPC::Channel> in, out; |
- base::Thread* in_thread_; |
- base::Thread* out_thread_; |
- MyCBListener cb_listener_; |
- MyCBListener null_listener_; |
-}; |
- |
-// This test is meant to provoke a kernel bug on OSX, and to prove |
-// that the workaround for it is working. It sets up two pipes and three |
-// threads, the producer thread creates socketpairs and sends one of the fds |
-// over pipe1 to the middleman thread. The middleman thread simply takes the fd |
-// sends it over pipe2 to the consumer thread. The consumer thread writes a byte |
-// to each fd it receives and then closes the pipe. The producer thread reads |
-// the bytes back from each pair of pipes and make sure that everything worked. |
-// This feedback mechanism makes sure that not too many file descriptors are |
-// in flight at the same time. For more info on the bug, see: |
-// http://crbug.com/298276 |
-class IPCMultiSendingFdsTest : public testing::Test { |
- public: |
- IPCMultiSendingFdsTest() |
- : received_(base::WaitableEvent::ResetPolicy::MANUAL, |
- base::WaitableEvent::InitialState::NOT_SIGNALED) {} |
- |
- void Producer(PipeChannelHelper* dest, |
- base::Thread* t, |
- int pipes_to_send) { |
- for (int i = 0; i < pipes_to_send; i++) { |
- received_.Reset(); |
- std::pair<int, int> pipe_fds = make_socket_pair(); |
- t->task_runner()->PostTask( |
- FROM_HERE, base::Bind(&PipeChannelHelper::Send, |
- base::Unretained(dest), pipe_fds.second)); |
- char tmp = 'x'; |
- CHECK_EQ(1, HANDLE_EINTR(write(pipe_fds.first, &tmp, 1))); |
- CHECK_EQ(0, IGNORE_EINTR(close(pipe_fds.first))); |
- received_.Wait(); |
- } |
- } |
- |
- void ConsumerHandleFD(int fd) { |
- char tmp = 'y'; |
- CHECK_EQ(1, HANDLE_EINTR(read(fd, &tmp, 1))); |
- CHECK_EQ(tmp, 'x'); |
- CHECK_EQ(0, IGNORE_EINTR(close(fd))); |
- received_.Signal(); |
- } |
- |
- base::Thread* CreateThread(const char* name) { |
- base::Thread* ret = new base::Thread(name); |
- base::Thread::Options options; |
- options.message_loop_type = base::MessageLoop::TYPE_IO; |
- ret->StartWithOptions(options); |
- return ret; |
- } |
- |
- void Run() { |
- // On my mac, this test fails roughly 35 times per |
- // million sends with low load, but much more with high load. |
- // Unless the workaround is in place. With 10000 sends, we |
- // should see at least a 3% failure rate. |
- const int pipes_to_send = 20000; |
- std::unique_ptr<base::Thread> producer(CreateThread("producer")); |
- std::unique_ptr<base::Thread> middleman(CreateThread("middleman")); |
- std::unique_ptr<base::Thread> consumer(CreateThread("consumer")); |
- PipeChannelHelper pipe1( |
- middleman.get(), |
- consumer.get(), |
- base::Bind(&IPCMultiSendingFdsTest::ConsumerHandleFD, |
- base::Unretained(this)), |
- pipes_to_send); |
- PipeChannelHelper pipe2( |
- producer.get(), |
- middleman.get(), |
- base::Bind(&PipeChannelHelper::Send, base::Unretained(&pipe1)), |
- pipes_to_send); |
- pipe1.Init(); |
- pipe2.Init(); |
- Producer(&pipe2, producer.get(), pipes_to_send); |
- } |
- |
- private: |
- base::WaitableEvent received_; |
-}; |
- |
-TEST_F(IPCMultiSendingFdsTest, StressTest) { |
- Run(); |
-} |
- |
} // namespace |
#endif // defined(OS_POSIX) |