summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-25 18:51:56 +0000
committerviettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-25 18:51:56 +0000
commit9e1d949234ada3ac3d696926b35da0db4a021136 (patch)
tree2d8262fa406f822070739de75ee600d34873fd94
parent0f19f78d719fba3ae0631970c8b2f5daa1014b87 (diff)
downloadchromium_src-9e1d949234ada3ac3d696926b35da0db4a021136.zip
chromium_src-9e1d949234ada3ac3d696926b35da0db4a021136.tar.gz
chromium_src-9e1d949234ada3ac3d696926b35da0db4a021136.tar.bz2
Mojo: Prevent SIGPIPE (on sockets generated by PlatformChannelPair) on Mac.
R=darin@chromium.org BUG=356195 Review URL: https://codereview.chromium.org/207453005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@259274 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--mojo/embedder/platform_channel_pair_posix.cc12
-rw-r--r--mojo/embedder/platform_channel_pair_posix_unittest.cc86
-rw-r--r--mojo/mojo.gyp1
3 files changed, 99 insertions, 0 deletions
diff --git a/mojo/embedder/platform_channel_pair_posix.cc b/mojo/embedder/platform_channel_pair_posix.cc
index d9e65ed..2d5e2ca 100644
--- a/mojo/embedder/platform_channel_pair_posix.cc
+++ b/mojo/embedder/platform_channel_pair_posix.cc
@@ -13,6 +13,7 @@
#include "base/logging.h"
#include "base/posix/global_descriptors.h"
#include "base/strings/string_number_conversions.h"
+#include "build/build_config.h"
#include "mojo/embedder/platform_handle.h"
namespace mojo {
@@ -40,6 +41,17 @@ PlatformChannelPair::PlatformChannelPair() {
PCHECK(fcntl(fds[0], F_SETFL, O_NONBLOCK) == 0);
PCHECK(fcntl(fds[1], F_SETFL, O_NONBLOCK) == 0);
+#if defined(OS_MACOSX)
+ // This turns off |SIGPIPE| when writing to a closed socket (causing it to
+ // fail with |EPIPE| instead). On Linux, we have to use |send...()| with
+ // |MSG_NOSIGNAL| -- which is not supported on Mac -- instead.
+ int no_sigpipe = 1;
+ PCHECK(setsockopt(fds[0], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
+ sizeof(no_sigpipe)) == 0);
+ PCHECK(setsockopt(fds[1], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
+ sizeof(no_sigpipe)) == 0);
+#endif // defined(OS_MACOSX)
+
server_handle_.reset(PlatformHandle(fds[0]));
DCHECK(server_handle_.is_valid());
client_handle_.reset(PlatformHandle(fds[1]));
diff --git a/mojo/embedder/platform_channel_pair_posix_unittest.cc b/mojo/embedder/platform_channel_pair_posix_unittest.cc
new file mode 100644
index 0000000..23271da
--- /dev/null
+++ b/mojo/embedder/platform_channel_pair_posix_unittest.cc
@@ -0,0 +1,86 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/embedder/platform_channel_pair.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "build/build_config.h" // TODO(vtl): Remove this.
+#include "mojo/embedder/scoped_platform_handle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace embedder {
+namespace {
+
+class PlatformChannelPairPosixTest : public testing::Test {
+ public:
+ PlatformChannelPairPosixTest() {}
+ virtual ~PlatformChannelPairPosixTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ // Make sure |SIGPIPE| isn't being ignored.
+ struct sigaction action = {};
+ action.sa_handler = SIG_DFL;
+ ASSERT_EQ(0, sigaction(SIGPIPE, &action, &old_action_));
+ }
+
+ virtual void TearDown() OVERRIDE {
+ // Restore the |SIGPIPE| handler.
+ ASSERT_EQ(0, sigaction(SIGPIPE, &old_action_, NULL));
+ }
+
+ private:
+ struct sigaction old_action_;
+
+ DISALLOW_COPY_AND_ASSIGN(PlatformChannelPairPosixTest);
+};
+
+// TODO(vtl): crbug.com/356195
+#if defined(OS_MACOSX)
+#define MAYBE_NoSigPipe NoSigPipe
+#else
+#define MAYBE_NoSigPipe DISABLED_NoSigPipe
+#endif
+TEST_F(PlatformChannelPairPosixTest, MAYBE_NoSigPipe) {
+ PlatformChannelPair channel_pair;
+
+ ScopedPlatformHandle server_handle = channel_pair.PassServerHandle().Pass();
+ ScopedPlatformHandle client_handle = channel_pair.PassClientHandle().Pass();
+
+ // Write to the client.
+ static const char kHello[] = "hello";
+ EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
+ write(client_handle.get().fd, kHello, sizeof(kHello)));
+
+ // Close the client.
+ client_handle.reset();
+
+ // Read from the server; this should be okay.
+ char buffer[100] = {};
+ EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
+ read(server_handle.get().fd, buffer, sizeof(buffer)));
+ EXPECT_STREQ(kHello, buffer);
+
+ // Try reading again.
+ ssize_t result = read(server_handle.get().fd, buffer, sizeof(buffer));
+ // We should probably get zero (for "end of file"), but -1 would also be okay.
+ EXPECT_TRUE(result == 0 || result == -1);
+ if (result == -1)
+ PLOG(WARNING) << "read (expected 0 for EOF)";
+
+ // However, |write()| should fail outright.
+ result = write(server_handle.get().fd, kHello, sizeof(kHello));
+ EXPECT_EQ(-1, result);
+ if (errno != EPIPE)
+ PLOG(WARNING) << "write (expected EPIPE)";
+}
+
+} // namespace
+} // namespace embedder
+} // namespace mojo
diff --git a/mojo/mojo.gyp b/mojo/mojo.gyp
index 37834b2..2d15e5a 100644
--- a/mojo/mojo.gyp
+++ b/mojo/mojo.gyp
@@ -180,6 +180,7 @@
],
'sources': [
'embedder/embedder_unittest.cc',
+ 'embedder/platform_channel_pair_posix_unittest.cc',
'system/core_impl_unittest.cc',
'system/core_test_base.cc',
'system/core_test_base.h',