Index: sandbox/linux/syscall_broker/broker_process_unittest.cc |
diff --git a/sandbox/linux/syscall_broker/broker_process_unittest.cc b/sandbox/linux/syscall_broker/broker_process_unittest.cc |
index e7d5442c3b1ac656096ed6465258a2c1bd886f64..997667c36ad8a6b1b0dd78be1086054feb711e4c 100644 |
--- a/sandbox/linux/syscall_broker/broker_process_unittest.cc |
+++ b/sandbox/linux/syscall_broker/broker_process_unittest.cc |
@@ -6,6 +6,7 @@ |
#include <errno.h> |
#include <fcntl.h> |
+#include <poll.h> |
#include <sys/resource.h> |
#include <sys/stat.h> |
#include <sys/types.h> |
@@ -24,6 +25,7 @@ |
#include "base/memory/scoped_ptr.h" |
#include "base/posix/eintr_wrapper.h" |
#include "base/posix/unix_domain_socket_linux.h" |
+#include "sandbox/linux/syscall_broker/broker_client.h" |
#include "sandbox/linux/tests/scoped_temporary_file.h" |
#include "sandbox/linux/tests/test_utils.h" |
#include "sandbox/linux/tests/unit_tests.h" |
@@ -31,10 +33,15 @@ |
namespace sandbox { |
+namespace syscall_broker { |
+ |
class BrokerProcessTestHelper { |
public: |
- static int get_ipc_socketpair(const BrokerProcess* broker) { |
- return broker->ipc_socketpair_; |
+ static void CloseChannel(BrokerProcess* broker) { broker->CloseChannel(); } |
+ // Get the client's IPC descriptor to send IPC requests directly. |
+ // TODO(jln): refator tests to get rid of this. |
+ static int GetIPCDescriptor(const BrokerProcess* broker) { |
+ return broker->broker_client_->GetIPCDescriptor(); |
} |
}; |
@@ -453,7 +460,7 @@ SANDBOX_TEST_ALLOW_NOISE(BrokerProcess, RecvMsgDescriptorLeak) { |
BrokerProcess open_broker(EPERM, read_whitelist, std::vector<std::string>()); |
SANDBOX_ASSERT(open_broker.Init(base::Bind(&NoOpCallback))); |
- const int ipc_fd = BrokerProcessTestHelper::get_ipc_socketpair(&open_broker); |
+ const int ipc_fd = BrokerProcessTestHelper::GetIPCDescriptor(&open_broker); |
SANDBOX_ASSERT(ipc_fd >= 0); |
static const char kBogus[] = "not a pickle"; |
@@ -472,4 +479,60 @@ SANDBOX_TEST_ALLOW_NOISE(BrokerProcess, RecvMsgDescriptorLeak) { |
SANDBOX_ASSERT(0 == IGNORE_EINTR(close(fd))); |
} |
+bool CloseFD(int fd) { |
+ PCHECK(0 == IGNORE_EINTR(close(fd))); |
+ return true; |
+} |
+ |
+// Return true if the other end of the |reader| pipe was closed, |
+// false if |timeout_in_seconds| was reached or another event |
+// or error occured. |
+bool WaitForClosedPipeWriter(int reader, int timeout_in_ms) { |
+ struct pollfd poll_fd = {reader, POLLIN | POLLRDHUP, 0}; |
+ const int num_events = HANDLE_EINTR(poll(&poll_fd, 1, timeout_in_ms)); |
+ if (1 == num_events && poll_fd.revents | POLLHUP) |
+ return true; |
+ return false; |
+} |
+ |
+// Closing the broker client's IPC channel should terminate the broker |
+// process. |
+TEST(BrokerProcess, BrokerDiesOnClosedChannel) { |
+ std::vector<std::string> read_whitelist; |
+ read_whitelist.push_back("/proc/cpuinfo"); |
+ |
+ // Get the writing end of a pipe into the broker (child) process so |
+ // that we can reliably detect when it dies. |
+ int lifeline_fds[2]; |
+ PCHECK(0 == pipe(lifeline_fds)); |
+ |
+ BrokerProcess open_broker(EPERM, read_whitelist, std::vector<std::string>(), |
+ true /* fast_check_in_client */, |
+ false /* quiet_failures_for_tests */); |
+ ASSERT_TRUE(open_broker.Init(base::Bind(&CloseFD, lifeline_fds[0]))); |
+ // Make sure the writing end only exists in the broker process. |
+ CloseFD(lifeline_fds[1]); |
+ base::ScopedFD reader(lifeline_fds[0]); |
+ |
+ const pid_t broker_pid = open_broker.broker_pid(); |
+ |
+ // This should cause the broker process to exit. |
+ BrokerProcessTestHelper::CloseChannel(&open_broker); |
+ |
+ const int kTimeoutInMilliseconds = 5000; |
+ const bool broker_lifeline_closed = |
+ WaitForClosedPipeWriter(reader.get(), kTimeoutInMilliseconds); |
+ // If the broker exited, its lifeline fd should be closed. |
+ ASSERT_TRUE(broker_lifeline_closed); |
+ // Now check that the broker has exited, but do not reap it. |
+ siginfo_t process_info; |
+ ASSERT_EQ(0, HANDLE_EINTR(waitid(P_PID, broker_pid, &process_info, |
+ WEXITED | WNOWAIT))); |
+ EXPECT_EQ(broker_pid, process_info.si_pid); |
+ EXPECT_EQ(CLD_EXITED, process_info.si_code); |
+ EXPECT_EQ(1, process_info.si_status); |
+} |
+ |
+} // namespace syscall_broker |
+ |
} // namespace sandbox |