nixd
Toggle main menu visibility
Loading...
Searching...
No Matches
nixd
lib
Support
ForkPiped.cpp
Go to the documentation of this file.
1
#include "
nixd/Support/ForkPiped.h
"
2
3
#include "
ForkPipedPlatform.h
"
4
5
#include <cerrno>
6
#include <fcntl.h>
7
8
#include <system_error>
9
#include <unistd.h>
10
#include <utility>
11
12
namespace
{
13
14
// Own every endpoint until it is transferred to the parent. This object is
15
// constructed before pipe creation so partial creation failures are covered.
16
struct
PipeDescriptors {
17
int
In[2] = {-1, -1};
18
int
Out[2] = {-1, -1};
19
int
Err[2] = {-1, -1};
20
21
PipeDescriptors() =
default
;
22
PipeDescriptors(
const
PipeDescriptors &) =
delete
;
23
PipeDescriptors &operator=(
const
PipeDescriptors &) =
delete
;
24
25
~PipeDescriptors() {
26
for
(
const
auto
*Pipe : {In, Out, Err})
27
for
(
int
I = 0; I < 2; ++I)
28
if
(Pipe[I] != -1)
29
close(Pipe[I]);
30
}
31
};
32
33
}
// namespace
34
35
int
nixd::forkPiped
(
int
&In,
int
&Out,
int
&Err) {
36
detail::PipeForkScope
Platform;
37
static
constexpr
int
READ = 0;
38
static
constexpr
int
WRITE = 1;
39
PipeDescriptors Pipes;
40
auto
&PipeIn = Pipes.In;
41
auto
&PipeOut = Pipes.Out;
42
auto
&PipeErr = Pipes.Err;
43
if
(Platform.
createPipe
(PipeIn) == -1 || Platform.
createPipe
(PipeOut) == -1 ||
44
Platform.
createPipe
(PipeErr) == -1)
45
throw
std::system_error(errno, std::generic_category());
46
47
// Keep the sources away from stdio, even if the caller closed fd 0, 1 or 2.
48
// This also ensures dup2 clears CLOEXEC rather than becoming a no-op.
49
for
(
auto
*Pipe : {PipeIn, PipeOut, PipeErr})
50
for
(
int
I = 0; I < 2; ++I)
51
if
(Pipe[I] <= STDERR_FILENO) {
52
int
FD = fcntl(Pipe[I], F_DUPFD_CLOEXEC, STDERR_FILENO + 1);
53
if
(FD == -1)
54
throw
std::system_error(errno, std::generic_category());
55
close(Pipe[I]);
56
Pipe[I] = FD;
57
}
58
59
pid_t Child = Platform.
forkProcess
();
60
if
(Child == -1)
61
throw
std::system_error(errno, std::generic_category());
62
63
if
(Child == 0) {
64
// Redirect stdin, stdout, stderr.
65
const
int
Sources[] = {PipeIn[READ], PipeOut[WRITE], PipeErr[WRITE]};
66
for
(
int
Target = STDIN_FILENO; Target <= STDERR_FILENO; ++Target) {
67
int
Result;
68
do
{
69
Result = dup2(Sources[Target], Target);
70
}
while
(Result == -1 && errno == EINTR);
71
if
(Result == -1)
72
_exit(127);
73
}
74
return
0;
75
}
76
77
In = std::exchange(PipeIn[WRITE], -1);
78
Out = std::exchange(PipeOut[READ], -1);
79
Err = std::exchange(PipeErr[READ], -1);
80
return
Child;
81
}
ForkPipedPlatform.h
ForkPiped.h
nixd::detail::PipeForkScope
Definition
ForkPipedPlatform.h:21
nixd::detail::PipeForkScope::createPipe
int createPipe(int Pipe[2]) const
Definition
ForkPipedPlatform.h:30
nixd::detail::PipeForkScope::forkProcess
pid_t forkProcess()
Definition
ForkPipedPlatform.h:39
nixd::forkPiped
int forkPiped(int &In, int &Out, int &Err)
fork this process and create some pipes connected to the new process.
Definition
ForkPiped.cpp:35
Generated by
1.17.0