Apache Mesos
pipe.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_OS_POSIX_PIPE_HPP__
14 #define __STOUT_OS_POSIX_PIPE_HPP__
15 
16 #include <unistd.h>
17 
18 #include <sys/syscall.h>
19 
20 #include <array>
21 
22 #include <stout/error.hpp>
23 #include <stout/try.hpp>
24 
25 #include <stout/os/posix/fcntl.hpp>
26 
27 namespace os {
28 
29 // Create pipes for interprocess communication. The pipe file descriptors
30 // will be marked O_CLOEXEC (atomically if the platform supports it). To
31 // pass the pipe to a child process, the caller should clear the CLOEXEC
32 // flag after fork(2) but before exec(2).
34 {
35  std::array<int, 2> result;
36 
37  // The pipe2() function appeared in FreeBSD 10.0.
38 #if defined(__FreeBSD__) && __FreeBSD_version >= 1000000
39 
40  if (::pipe2(result.data(), O_CLOEXEC) < 0) {
41  return ErrnoError();
42  }
43 
44 #else
45 
46  // pipe2() appeared in Linux 2.6.27 and glibc 2.9.
47 #if defined(__linux__) && defined(SYS_pipe2)
48  if (::syscall(SYS_pipe2, result.data(), O_CLOEXEC) == 0) {
49  return result;
50  }
51 
52  // Fall back if the kernel doesn't support pipe2().
53  if (errno != ENOSYS) {
54  return ErrnoError();
55  }
56 #endif
57 
58  if (::pipe(result.data()) < 0) {
59  return ErrnoError();
60  }
61 
63 
64  cloexec = os::cloexec(result[0]);
65  if (cloexec.isError()) {
66  Error error = Error("Failed to cloexec pipe: " + cloexec.error());
67  ::close(result[0]);
68  ::close(result[1]);
69  return error;
70  }
71 
72  cloexec = os::cloexec(result[1]);
73  if (cloexec.isError()) {
74  Error error = Error("Failed to cloexec pipe: " + cloexec.error());
75  ::close(result[0]);
76  ::close(result[1]);
77  return error;
78  }
79 
80 #endif
81 
82  return result;
83 }
84 
85 } // namespace os {
86 
87 #endif // __STOUT_OS_POSIX_PIPE_HPP__
Definition: nothing.hpp:16
Try< std::array< int, 2 > > pipe()
Definition: pipe.hpp:33
Definition: errorbase.hpp:36
Definition: check.hpp:33
Definition: errorbase.hpp:50
Definition: posix_signalhandler.hpp:23
constexpr int O_CLOEXEC
Definition: open.hpp:41
Try< Nothing > close(int fd)
Definition: close.hpp:24
Try< Nothing > cloexec(int fd)
Definition: fcntl.hpp:27
static Try error(const E &e)
Definition: try.hpp:43
bool isError() const
Definition: try.hpp:78
std::string error(const std::string &msg, uint32_t code)