You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by jp...@apache.org on 2018/08/17 22:21:45 UTC

[mesos] 01/02: Updated `os::pipe()` to always return O_CLOEXEC descriptors.

This is an automated email from the ASF dual-hosted git repository.

jpeach pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git

commit 2388ca4bd3be3ed5da266e74b518dd284de1be94
Author: James Peach <jp...@apache.org>
AuthorDate: Fri Aug 17 11:45:52 2018 -0700

    Updated `os::pipe()` to always return O_CLOEXEC descriptors.
    
    Updated `os::pipe()` to always return O_CLOEXEC descriptors,
    atomically if we are on Linux or FreeBSD and the `pipe2(2)`
    system call is available.
    
    Review: https://reviews.apache.org/r/63270/
---
 3rdparty/stout/include/stout/os/posix/pipe.hpp | 52 +++++++++++++++++++++++++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/3rdparty/stout/include/stout/os/posix/pipe.hpp b/3rdparty/stout/include/stout/os/posix/pipe.hpp
index ac76224..9838d7b 100644
--- a/3rdparty/stout/include/stout/os/posix/pipe.hpp
+++ b/3rdparty/stout/include/stout/os/posix/pipe.hpp
@@ -15,20 +15,70 @@
 
 #include <unistd.h>
 
+#include <sys/syscall.h>
+
 #include <array>
 
 #include <stout/error.hpp>
 #include <stout/try.hpp>
 
+#include <stout/os/posix/fcntl.hpp>
+
 namespace os {
 
-// Create pipes for interprocess communication.
+// Create pipes for interprocess communication. The pipe file descriptors
+// will be marked O_CLOEXEC (atomically if the platform supports it). To
+// pass the pipe to a child process, the caller should clear the CLOEXEC
+// flag after fork(2) but before exec(2).
 inline Try<std::array<int, 2>> pipe()
 {
   std::array<int, 2> result;
+
+  // The pipe2() function appeared in FreeBSD 10.0.
+#if defined(_FreeBSD__) && __FreeBSD_version >= 1000000
+
+  if (::pipe2(result.data(), O_CLOEXEC) < 0) {
+    return ErrnoError();
+  }
+
+#else
+
+  // pipe2() appeared in Linux 2.6.27 and glibc 2.9.
+#if defined(__linux__) && defined(SYS_pipe2)
+  if (::syscall(SYS_pipe2, result.data(), O_CLOEXEC) == 0) {
+    return result;
+  }
+
+  // Fall back if the kernel doesn't support pipe2().
+  if (errno != ENOSYS) {
+    return ErrnoError();
+  }
+#endif
+
   if (::pipe(result.data()) < 0) {
     return ErrnoError();
   }
+
+  Try<Nothing> cloexec = Nothing();
+
+  cloexec = os::cloexec(result[0]);
+  if (cloexec.isError()) {
+    Error error = Error("Failed to cloexec pipe: " + cloexec.error());
+    ::close(result[0]);
+    ::close(result[1]);
+    return error;
+  }
+
+  cloexec = os::cloexec(result[1]);
+  if (cloexec.isError()) {
+    Error error = Error("Failed to cloexec pipe: " + cloexec.error());
+    ::close(result[0]);
+    ::close(result[1]);
+    return error;
+  }
+
+#endif
+
   return result;
 }