Index: ipc/sync_socket_unittest.cc |
diff --git a/ipc/sync_socket_unittest.cc b/ipc/sync_socket_unittest.cc |
index 79cf6c3c33d1cbcc56d97d22616c443623e05a06..173715a5df969ab6bb4539dbd5b4498466c26d66 100644 |
--- a/ipc/sync_socket_unittest.cc |
+++ b/ipc/sync_socket_unittest.cc |
@@ -8,8 +8,10 @@ |
#include <string> |
#include <sstream> |
+#include "base/bind.h" |
#include "base/message_loop.h" |
#include "base/process_util.h" |
+#include "base/threading/thread.h" |
#include "ipc/ipc_channel_proxy.h" |
#include "ipc/ipc_tests.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -52,7 +54,7 @@ const size_t kHelloStringLength = arraysize(kHelloString); |
// messages from the client. |
class SyncSocketServerListener : public IPC::Channel::Listener { |
public: |
- SyncSocketServerListener() : chan_(NULL) { |
+ SyncSocketServerListener() : chan_(NULL) { |
} |
void Init(IPC::Channel* chan) { |
@@ -171,25 +173,25 @@ TEST_F(SyncSocketTest, SanityTest) { |
base::ProcessHandle server_process = SpawnChild(SYNC_SOCKET_SERVER, &chan); |
ASSERT_TRUE(server_process); |
// Create a pair of SyncSockets. |
- base::SyncSocket* pair[2]; |
- base::SyncSocket::CreatePair(pair); |
+ base::SyncSocket pair[2]; |
+ base::SyncSocket::CreatePair(&pair[0], &pair[1]); |
// Immediately after creation there should be no pending bytes. |
- EXPECT_EQ(0U, pair[0]->Peek()); |
- EXPECT_EQ(0U, pair[1]->Peek()); |
+ EXPECT_EQ(0U, pair[0].Peek()); |
+ EXPECT_EQ(0U, pair[1].Peek()); |
base::SyncSocket::Handle target_handle; |
// Connect the channel and listener. |
ASSERT_TRUE(chan.Connect()); |
- listener.Init(pair[0], &chan); |
+ listener.Init(&pair[0], &chan); |
#if defined(OS_WIN) |
// On windows we need to duplicate the handle into the server process. |
- BOOL retval = DuplicateHandle(GetCurrentProcess(), pair[1]->handle(), |
+ BOOL retval = DuplicateHandle(GetCurrentProcess(), pair[1].handle(), |
server_process, &target_handle, |
0, FALSE, DUPLICATE_SAME_ACCESS); |
EXPECT_TRUE(retval); |
// Set up a message to pass the handle to the server. |
IPC::Message* msg = new MsgClassSetHandle(target_handle); |
#else |
- target_handle = pair[1]->handle(); |
+ target_handle = pair[1].handle(); |
// Set up a message to pass the handle to the server. |
base::FileDescriptor filedesc(target_handle, false); |
IPC::Message* msg = new MsgClassSetHandle(filedesc); |
@@ -198,8 +200,45 @@ TEST_F(SyncSocketTest, SanityTest) { |
// Use the current thread as the I/O thread. |
MessageLoop::current()->Run(); |
// Shut down. |
- delete pair[0]; |
- delete pair[1]; |
+ pair[0].Close(); |
+ pair[1].Close(); |
EXPECT_TRUE(base::WaitForSingleProcess(server_process, 5000)); |
base::CloseProcessHandle(server_process); |
} |
+ |
+static void BlockingRead(base::SyncSocket* socket, size_t* received) { |
+ // Notify the parent thread that we're up and running. |
+ socket->Send(kHelloString, kHelloStringLength); |
+ char buf[0xff]; // Won't ever be filled. |
+ *received = socket->Receive(buf, arraysize(buf)); |
+} |
+ |
+// Tests that we can safely end a blocking Receive operation on one thread |
+// from another thread by disconnecting (but not closing) the socket. |
+TEST_F(SyncSocketTest, DisconnectTest) { |
+ base::CancelableSyncSocket pair[2]; |
+ ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1])); |
+ |
+ base::Thread worker("BlockingThread"); |
+ worker.Start(); |
+ |
+ // Try to do a blocking read from one of the sockets on the worker thread. |
+ size_t received = 1U; // Initialize to an unexpected value. |
+ worker.message_loop()->PostTask(FROM_HERE, |
+ base::Bind(&BlockingRead, &pair[0], &received)); |
+ |
+ // Wait for the worker thread to say hello. |
+ char hello[kHelloStringLength] = {0}; |
+ pair[1].Receive(&hello[0], sizeof(hello)); |
+ VLOG(1) << "Received: " << hello; |
+ // Give the worker a chance to start Receive(). |
+ base::PlatformThread::YieldCurrentThread(); |
+ |
+ // Now shut down the socket that the thread is issuing a blocking read on |
+ // which should cause Receive to return with an error. |
+ pair[0].Shutdown(); |
+ |
+ worker.Stop(); |
+ |
+ EXPECT_EQ(0U, received); |
+} |