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

Side by Side Diff: ipc/ipc_channel_posix_unittest.cc

Issue 150893002: Fix posix IPC channel hanging problem. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: reordered early exit, as requested 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
(...skipping 21 matching lines...) Expand all
76 virtual void OnChannelListenError() OVERRIDE { 78 virtual void OnChannelListenError() OVERRIDE {
77 status_ = LISTEN_ERROR; 79 status_ = LISTEN_ERROR;
78 if (!quit_only_on_message_) { 80 if (!quit_only_on_message_) {
79 QuitRunLoop(); 81 QuitRunLoop();
80 } 82 }
81 } 83 }
82 84
83 STATUS status() { return status_; } 85 STATUS status() { return status_; }
84 86
85 void QuitRunLoop() { 87 void QuitRunLoop() {
86 base::MessageLoopForIO::current()->QuitNow(); 88 base::MessageLoopForIO* loop = base::MessageLoopForIO::current();
89 if (loop->is_running()) {
90 loop->QuitNow();
91 } else {
92 // Die as soon as Run is called.
93 loop->PostTask(FROM_HERE, loop->QuitClosure());
94 }
87 } 95 }
88 96
89 private: 97 private:
90 // The current status of the listener. 98 // The current status of the listener.
91 STATUS status_; 99 STATUS status_;
92 // If |quit_only_on_message_| then the listener will only break out of 100 // If |quit_only_on_message_| then the listener will only break out of
93 // the run loop when kQuitMessage is received. 101 // the run loop when kQuitMessage is received.
94 bool quit_only_on_message_; 102 bool quit_only_on_message_;
95 }; 103 };
96 104
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 } 187 }
180 handle->socket.fd = socket_fd; 188 handle->socket.fd = socket_fd;
181 } 189 }
182 190
183 void IPCChannelPosixTest::SpinRunLoop(base::TimeDelta delay) { 191 void IPCChannelPosixTest::SpinRunLoop(base::TimeDelta delay) {
184 base::MessageLoopForIO* loop = base::MessageLoopForIO::current(); 192 base::MessageLoopForIO* loop = base::MessageLoopForIO::current();
185 // Post a quit task so that this loop eventually ends and we don't hang 193 // 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 194 // 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 195 // that because all tests use a IPCChannelPosixTestListener which quits the
188 // current run loop on any channel activity. 196 // current run loop on any channel activity.
189 loop->PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(), delay); 197 loop->PostDelayedTask(FROM_HERE, loop->QuitClosure(), delay);
190 loop->Run(); 198 loop->Run();
191 } 199 }
192 200
193 TEST_F(IPCChannelPosixTest, BasicListen) { 201 TEST_F(IPCChannelPosixTest, BasicListen) {
194 const std::string kChannelName = 202 const std::string kChannelName =
195 GetChannelDirName() + "/IPCChannelPosixTest_BasicListen"; 203 GetChannelDirName() + "/IPCChannelPosixTest_BasicListen";
196 204
197 // Test creating a socket that is listening. 205 // Test creating a socket that is listening.
198 IPC::ChannelHandle handle(kChannelName); 206 IPC::ChannelHandle handle(kChannelName);
199 SetUpSocket(&handle, IPC::Channel::MODE_NAMED_SERVER); 207 SetUpSocket(&handle, IPC::Channel::MODE_NAMED_SERVER);
(...skipping 21 matching lines...) Expand all
221 channel.Close(); 229 channel.Close();
222 ASSERT_TRUE(IGNORE_EINTR(close(pipe_fds[1])) == 0); 230 ASSERT_TRUE(IGNORE_EINTR(close(pipe_fds[1])) == 0);
223 231
224 // Make sure that we can use the socket that is created for us by 232 // Make sure that we can use the socket that is created for us by
225 // a standard channel. 233 // a standard channel.
226 IPC::Channel channel2(socket_name, IPC::Channel::MODE_SERVER, NULL); 234 IPC::Channel channel2(socket_name, IPC::Channel::MODE_SERVER, NULL);
227 ASSERT_TRUE(channel2.Connect()); 235 ASSERT_TRUE(channel2.Connect());
228 ASSERT_FALSE(channel2.AcceptsConnections()); 236 ASSERT_FALSE(channel2.AcceptsConnections());
229 } 237 }
230 238
239 // If a connection closes right before a Send() call, we may end up closing
240 // the connection without notifying the listener, which can cause hangs in
241 // sync_message_filter and others. Make sure the listener is notified.
242 TEST_F(IPCChannelPosixTest, SendHangTest) {
243 IPCChannelPosixTestListener out_listener(true);
244 IPCChannelPosixTestListener in_listener(true);
245 IPC::ChannelHandle in_handle("IN");
246 IPC::Channel in_chan(in_handle, IPC::Channel::MODE_SERVER, &in_listener);
247 base::FileDescriptor out_fd(in_chan.TakeClientFileDescriptor(), false);
248 IPC::ChannelHandle out_handle("OUT", out_fd);
249 IPC::Channel out_chan(out_handle, IPC::Channel::MODE_CLIENT, &out_listener);
250 ASSERT_TRUE(in_chan.Connect());
251 ASSERT_TRUE(out_chan.Connect());
252 in_chan.Close(); // simulate remote process dying at an unfortunate time.
253 // Send will fail, because it cannot write the message.
254 ASSERT_FALSE(out_chan.Send(new IPC::Message(
255 0, // routing_id
256 kQuitMessage, // message type
257 IPC::Message::PRIORITY_NORMAL)));
258 ASSERT_EQ(IPCChannelPosixTestListener::CHANNEL_ERROR, out_listener.status());
259 }
260
261 // If a connection closes right before a Connect() call, we may end up closing
262 // the connection without notifying the listener, which can cause hangs in
263 // sync_message_filter and others. Make sure the listener is notified.
264 TEST_F(IPCChannelPosixTest, AcceptHangTest) {
265 IPCChannelPosixTestListener out_listener(true);
266 IPCChannelPosixTestListener in_listener(true);
267 IPC::ChannelHandle in_handle("IN");
268 IPC::Channel in_chan(in_handle, IPC::Channel::MODE_SERVER, &in_listener);
269 base::FileDescriptor out_fd(in_chan.TakeClientFileDescriptor(), false);
270 IPC::ChannelHandle out_handle("OUT", out_fd);
271 IPC::Channel out_chan(out_handle, IPC::Channel::MODE_CLIENT, &out_listener);
272 ASSERT_TRUE(in_chan.Connect());
273 in_chan.Close(); // simulate remote process dying at an unfortunate time.
274 ASSERT_FALSE(out_chan.Connect());
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