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

Side by Side Diff: ipc/ipc_channel_posix_unittest.cc

Issue 172773002: Fix posix IPC channel hanging problem, take 3 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: removed change that is not needed anymore Created 6 years, 10 months 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_channel_posix.cc ('k') | no next file » | 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 // These tests are POSIX only. 5 // These tests are POSIX only.
6 6
7 #include "ipc/ipc_channel_posix.h" 7 #include "ipc/ipc_channel_posix.h"
8 8
9 #include <fcntl.h> 9 #include <fcntl.h>
10 #include <sys/socket.h> 10 #include <sys/socket.h>
(...skipping 23 matching lines...) Expand all
34 enum STATUS { 34 enum STATUS {
35 DISCONNECTED, 35 DISCONNECTED,
36 MESSAGE_RECEIVED, 36 MESSAGE_RECEIVED,
37 CHANNEL_ERROR, 37 CHANNEL_ERROR,
38 CONNECTED, 38 CONNECTED,
39 DENIED, 39 DENIED,
40 LISTEN_ERROR 40 LISTEN_ERROR
41 }; 41 };
42 42
43 IPCChannelPosixTestListener(bool quit_only_on_message) 43 IPCChannelPosixTestListener(bool quit_only_on_message)
44 : status_(DISCONNECTED), quit_only_on_message_(quit_only_on_message) {} 44 : status_(DISCONNECTED),
45 quit_only_on_message_(quit_only_on_message) {
46 }
45 47
46 virtual ~IPCChannelPosixTestListener() {} 48 virtual ~IPCChannelPosixTestListener() {}
47 49
48 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { 50 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
49 EXPECT_EQ(message.type(), kQuitMessage); 51 EXPECT_EQ(message.type(), kQuitMessage);
50 status_ = MESSAGE_RECEIVED; 52 status_ = MESSAGE_RECEIVED;
51 QuitRunLoop(); 53 QuitRunLoop();
52 return true; 54 return true;
53 } 55 }
54 56
55 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE { 57 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
56 status_ = CONNECTED; 58 status_ = CONNECTED;
57 if (!quit_only_on_message_) { 59 if (!quit_only_on_message_) {
58 QuitRunLoop(); 60 QuitRunLoop();
59 } 61 }
60 } 62 }
61 63
62 virtual void OnChannelError() OVERRIDE { 64 virtual void OnChannelError() OVERRIDE {
63 status_ = CHANNEL_ERROR; 65 status_ = CHANNEL_ERROR;
64 if (!quit_only_on_message_) { 66 QuitRunLoop();
65 QuitRunLoop();
66 }
67 } 67 }
68 68
69 virtual void OnChannelDenied() OVERRIDE { 69 virtual void OnChannelDenied() OVERRIDE {
70 status_ = DENIED; 70 status_ = DENIED;
71 if (!quit_only_on_message_) { 71 if (!quit_only_on_message_) {
72 QuitRunLoop(); 72 QuitRunLoop();
73 } 73 }
74 } 74 }
75 75
76 virtual void OnChannelListenError() OVERRIDE { 76 virtual void OnChannelListenError() OVERRIDE {
77 status_ = LISTEN_ERROR; 77 status_ = LISTEN_ERROR;
78 if (!quit_only_on_message_) { 78 if (!quit_only_on_message_) {
79 QuitRunLoop(); 79 QuitRunLoop();
80 } 80 }
81 } 81 }
82 82
83 STATUS status() { return status_; } 83 STATUS status() { return status_; }
84 84
85 void QuitRunLoop() { 85 void QuitRunLoop() {
86 base::MessageLoopForIO::current()->QuitNow(); 86 base::MessageLoopForIO* loop = base::MessageLoopForIO::current();
87 if (loop->is_running()) {
88 loop->QuitNow();
89 } else {
90 // Die as soon as Run is called.
91 loop->PostTask(FROM_HERE, loop->QuitClosure());
92 }
87 } 93 }
88 94
89 private: 95 private:
90 // The current status of the listener. 96 // The current status of the listener.
91 STATUS status_; 97 STATUS status_;
92 // If |quit_only_on_message_| then the listener will only break out of 98 // If |quit_only_on_message_| then the listener will only break out of
93 // the run loop when kQuitMessage is received. 99 // the run loop when kQuitMessage is received.
94 bool quit_only_on_message_; 100 bool quit_only_on_message_;
95 }; 101 };
96 102
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 } 185 }
180 handle->socket.fd = socket_fd; 186 handle->socket.fd = socket_fd;
181 } 187 }
182 188
183 void IPCChannelPosixTest::SpinRunLoop(base::TimeDelta delay) { 189 void IPCChannelPosixTest::SpinRunLoop(base::TimeDelta delay) {
184 base::MessageLoopForIO* loop = base::MessageLoopForIO::current(); 190 base::MessageLoopForIO* loop = base::MessageLoopForIO::current();
185 // Post a quit task so that this loop eventually ends and we don't hang 191 // Post a quit task so that this loop eventually ends and we don't hang
186 // in the case of a bad test. Usually, the run loop will quit sooner than 192 // in the case of a bad test. Usually, the run loop will quit sooner than
187 // that because all tests use a IPCChannelPosixTestListener which quits the 193 // that because all tests use a IPCChannelPosixTestListener which quits the
188 // current run loop on any channel activity. 194 // current run loop on any channel activity.
189 loop->PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(), delay); 195 loop->PostDelayedTask(FROM_HERE, loop->QuitClosure(), delay);
190 loop->Run(); 196 loop->Run();
191 } 197 }
192 198
193 TEST_F(IPCChannelPosixTest, BasicListen) { 199 TEST_F(IPCChannelPosixTest, BasicListen) {
194 const std::string kChannelName = 200 const std::string kChannelName =
195 GetChannelDirName() + "/IPCChannelPosixTest_BasicListen"; 201 GetChannelDirName() + "/IPCChannelPosixTest_BasicListen";
196 202
197 // Test creating a socket that is listening. 203 // Test creating a socket that is listening.
198 IPC::ChannelHandle handle(kChannelName); 204 IPC::ChannelHandle handle(kChannelName);
199 SetUpSocket(&handle, IPC::Channel::MODE_NAMED_SERVER); 205 SetUpSocket(&handle, IPC::Channel::MODE_NAMED_SERVER);
(...skipping 21 matching lines...) Expand all
221 channel.Close(); 227 channel.Close();
222 ASSERT_TRUE(IGNORE_EINTR(close(pipe_fds[1])) == 0); 228 ASSERT_TRUE(IGNORE_EINTR(close(pipe_fds[1])) == 0);
223 229
224 // Make sure that we can use the socket that is created for us by 230 // Make sure that we can use the socket that is created for us by
225 // a standard channel. 231 // a standard channel.
226 IPC::Channel channel2(socket_name, IPC::Channel::MODE_SERVER, NULL); 232 IPC::Channel channel2(socket_name, IPC::Channel::MODE_SERVER, NULL);
227 ASSERT_TRUE(channel2.Connect()); 233 ASSERT_TRUE(channel2.Connect());
228 ASSERT_FALSE(channel2.AcceptsConnections()); 234 ASSERT_FALSE(channel2.AcceptsConnections());
229 } 235 }
230 236
237 // If a connection closes right before a Send() call, we may end up closing
238 // the connection without notifying the listener, which can cause hangs in
239 // sync_message_filter and others. Make sure the listener is notified.
240 TEST_F(IPCChannelPosixTest, SendHangTest) {
241 IPCChannelPosixTestListener out_listener(true);
242 IPCChannelPosixTestListener in_listener(true);
243 IPC::ChannelHandle in_handle("IN");
244 IPC::Channel in_chan(in_handle, IPC::Channel::MODE_SERVER, &in_listener);
245 base::FileDescriptor out_fd(in_chan.TakeClientFileDescriptor(), false);
246 IPC::ChannelHandle out_handle("OUT", out_fd);
247 IPC::Channel out_chan(out_handle, IPC::Channel::MODE_CLIENT, &out_listener);
248 ASSERT_TRUE(in_chan.Connect());
249 ASSERT_TRUE(out_chan.Connect());
250 in_chan.Close(); // simulate remote process dying at an unfortunate time.
251 // Send will fail, because it cannot write the message.
252 ASSERT_FALSE(out_chan.Send(new IPC::Message(
253 0, // routing_id
254 kQuitMessage, // message type
255 IPC::Message::PRIORITY_NORMAL)));
256 SpinRunLoop(TestTimeouts::action_max_timeout());
257 ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, out_listener.status());
258 }
259
260 // If a connection closes right before a Connect() call, we may end up closing
261 // the connection without notifying the listener, which can cause hangs in
262 // sync_message_filter and others. Make sure the listener is notified.
263 TEST_F(IPCChannelPosixTest, AcceptHangTest) {
264 IPCChannelPosixTestListener out_listener(true);
265 IPCChannelPosixTestListener in_listener(true);
266 IPC::ChannelHandle in_handle("IN");
267 IPC::Channel in_chan(in_handle, IPC::Channel::MODE_SERVER, &in_listener);
268 base::FileDescriptor out_fd(in_chan.TakeClientFileDescriptor(), false);
269 IPC::ChannelHandle out_handle("OUT", out_fd);
270 IPC::Channel out_chan(out_handle, IPC::Channel::MODE_CLIENT, &out_listener);
271 ASSERT_TRUE(in_chan.Connect());
272 in_chan.Close(); // simulate remote process dying at an unfortunate time.
273 ASSERT_FALSE(out_chan.Connect());
274 SpinRunLoop(TestTimeouts::action_max_timeout());
275 ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, out_listener.status());
276 }
277
231 TEST_F(IPCChannelPosixTest, AdvancedConnected) { 278 TEST_F(IPCChannelPosixTest, AdvancedConnected) {
232 // Test creating a connection to an external process. 279 // Test creating a connection to an external process.
233 IPCChannelPosixTestListener listener(false); 280 IPCChannelPosixTestListener listener(false);
234 IPC::ChannelHandle chan_handle(GetConnectionSocketName()); 281 IPC::ChannelHandle chan_handle(GetConnectionSocketName());
235 SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER); 282 SetUpSocket(&chan_handle, IPC::Channel::MODE_NAMED_SERVER);
236 IPC::Channel channel(chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener); 283 IPC::Channel channel(chan_handle, IPC::Channel::MODE_NAMED_SERVER, &listener);
237 ASSERT_TRUE(channel.Connect()); 284 ASSERT_TRUE(channel.Connect());
238 ASSERT_TRUE(channel.AcceptsConnections()); 285 ASSERT_TRUE(channel.AcceptsConnections());
239 ASSERT_FALSE(channel.HasAcceptedConnection()); 286 ASSERT_FALSE(channel.HasAcceptedConnection());
240 287
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 if (connected) { 464 if (connected) {
418 IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout()); 465 IPCChannelPosixTest::SpinRunLoop(TestTimeouts::action_max_timeout());
419 EXPECT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status()); 466 EXPECT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, listener.status());
420 } else { 467 } else {
421 EXPECT_EQ(IPCChannelPosixTestListener::DISCONNECTED, listener.status()); 468 EXPECT_EQ(IPCChannelPosixTestListener::DISCONNECTED, listener.status());
422 } 469 }
423 return 0; 470 return 0;
424 } 471 }
425 472
426 } // namespace 473 } // namespace
OLDNEW
« no previous file with comments | « ipc/ipc_channel_posix.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698