Open MessagePumpLibevent's pipe with O_CLOEXEC

This prevents the pipe's fds from being leaked into child processes.
This is a cherry-pick of https://crrev.com/80c77bfd86 .

TEST=git cl try
BUG=chromium:653930

Change-Id: I1d9ea26e41a23dc7ca5cd6d4b2133a2e69b1259c
Reviewed-on: https://chromium-review.googlesource.com/395446
Commit-Ready: Luis Hector Chavez <lhchavez@google.com>
Tested-by: Luis Hector Chavez <lhchavez@google.com>
Reviewed-by: Luis Hector Chavez <lhchavez@google.com>
diff --git a/base/files/file_util.h b/base/files/file_util.h
index 8fd9fff..dbad7e5 100644
--- a/base/files/file_util.h
+++ b/base/files/file_util.h
@@ -359,6 +359,17 @@
 BASE_EXPORT bool SetNonBlocking(int fd);
 
 #if defined(OS_POSIX)
+// Creates a non-blocking, close-on-exec pipe.
+// This creates a non-blocking pipe that is not intended to be shared with any
+// child process. This will be done atomically if the operating system supports
+// it. Returns true if it was able to create the pipe, otherwise false.
+BASE_EXPORT bool CreateLocalNonBlockingPipe(int fds[2]);
+
+// Sets the given |fd| to close-on-exec mode.
+// Returns true if it was able to set it in the close-on-exec mode, otherwise
+// false.
+BASE_EXPORT bool SetCloseOnExec(int fd);
+
 // Test that |path| can only be changed by a given user and members of
 // a given set of groups.
 // Specifically, test that all parts of |path| under (and including) |base|:
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc
index 599759a..8462495 100644
--- a/base/files/file_util_posix.cc
+++ b/base/files/file_util_posix.cc
@@ -349,6 +349,29 @@
 }
 #endif  // !defined(OS_NACL_NONSFI)
 
+bool CreateLocalNonBlockingPipe(int fds[2]) {
+#if defined(OS_LINUX)
+  return pipe2(fds, O_CLOEXEC | O_NONBLOCK) == 0;
+#else
+  int raw_fds[2];
+  if (pipe(raw_fds) != 0)
+    return false;
+  ScopedFD fd_out(raw_fds[0]);
+  ScopedFD fd_in(raw_fds[1]);
+  if (!SetCloseOnExec(fd_out.get()))
+    return false;
+  if (!SetCloseOnExec(fd_in.get()))
+    return false;
+  if (!SetNonBlocking(fd_out.get()))
+    return false;
+  if (!SetNonBlocking(fd_in.get()))
+    return false;
+  fds[0] = fd_out.release();
+  fds[1] = fd_in.release();
+  return true;
+#endif
+}
+
 bool SetNonBlocking(int fd) {
   const int flags = fcntl(fd, F_GETFL);
   if (flags == -1)
@@ -360,6 +383,21 @@
   return true;
 }
 
+bool SetCloseOnExec(int fd) {
+#if defined(OS_NACL_NONSFI)
+  const int flags = 0;
+#else
+  const int flags = fcntl(fd, F_GETFD);
+  if (flags == -1)
+    return false;
+  if (flags & FD_CLOEXEC)
+    return true;
+#endif  // defined(OS_NACL_NONSFI)
+  if (HANDLE_EINTR(fcntl(fd, F_SETFD, flags | FD_CLOEXEC)) == -1)
+    return false;
+  return true;
+}
+
 bool PathExists(const FilePath& path) {
   ThreadRestrictions::AssertIOAllowed();
 #if defined(OS_ANDROID)
diff --git a/base/message_loop/message_pump_libevent.cc b/base/message_loop/message_pump_libevent.cc
index 5aa5567..5f20447 100644
--- a/base/message_loop/message_pump_libevent.cc
+++ b/base/message_loop/message_pump_libevent.cc
@@ -292,16 +292,8 @@
 
 bool MessagePumpLibevent::Init() {
   int fds[2];
-  if (pipe(fds)) {
-    DLOG(ERROR) << "pipe() failed, errno: " << errno;
-    return false;
-  }
-  if (!SetNonBlocking(fds[0])) {
-    DLOG(ERROR) << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
-    return false;
-  }
-  if (!SetNonBlocking(fds[1])) {
-    DLOG(ERROR) << "SetNonBlocking for pipe fd[1] failed, errno: " << errno;
+  if (!CreateLocalNonBlockingPipe(fds)) {
+    DPLOG(ERROR) << "pipe creation failed";
     return false;
   }
   wakeup_pipe_out_ = fds[0];