diff options
author | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-25 18:51:56 +0000 |
---|---|---|
committer | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-25 18:51:56 +0000 |
commit | 9e1d949234ada3ac3d696926b35da0db4a021136 (patch) | |
tree | 2d8262fa406f822070739de75ee600d34873fd94 | |
parent | 0f19f78d719fba3ae0631970c8b2f5daa1014b87 (diff) | |
download | chromium_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.cc | 12 | ||||
-rw-r--r-- | mojo/embedder/platform_channel_pair_posix_unittest.cc | 86 | ||||
-rw-r--r-- | mojo/mojo.gyp | 1 |
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', |