1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
use Result;
use ;
use ;
/// Representation of a running or exited child process,
/// similar to `std::process::Child`.
///
/// This structure is used to represent and manage child processes.
/// A child process is created via the `fork` or `fork_fn` functions.
///
/// There is no implementation of [`Drop`](std::ops::Drop) for child
/// processes, so if you do not ensure the Child has exited then it
/// will continue to run, even after the Child handle to the child
/// process has gone out of scope.
///
/// Calling [`wait`](Child::wait) will make the parent process wait
/// until the child has actually exited before continuing.
/// Result of a [`fork`] operation.
/// In the parent process [`fork`] will return [`Fork::Parent`],
/// while in the child it will return [`Fork::Child`].
///
/// The `Parent` variant holds a struct that can be used to
/// wait for the child process to exit.
///
/// Forks the current process, creating a new child process
/// that inherits the state of the parent process.
///
/// # Notes
/// Executing code after creating a fork needs to be done
/// carefully. It is recommended that the process is single
/// threaded at the time of forking, or that extra care has
/// been taken about the other threads in the process before
/// forking.
///
/// The new process will contain a copy of the process state.
/// This allows the child process to continue directly where
/// the parent left off.
/// But the child process will only contain a copy of the
/// calling thread. All other threads in the process will not
/// be reflected in the child process. This is particularly
/// relevant when one of the (non-calling) threads is holding
/// a mutex. That mutex will never be released in the child
/// process. This is even true is don't use mutexes yourself,
/// as some of these mutexes might be part of the system
/// libraries (even by the libraries that `cutlery` uses
/// internally), e.g., the malloc implementation could use a
/// mutex.
///
/// File descriptors will be shared form the parent to the
/// child. This allows you to share pipes between the two
/// processes for communication. But care needs to be taken
/// as operations on those file descriptors can trigger
/// deadlocks or race conditions between the parent and the
/// child.
///
/// ## Example
/// ```rust
/// # use cutlery::*;
/// match fork()? {
/// Fork::Parent(mut child) => {
/// let status = child.wait()?;
/// assert_eq!(status, 42);
/// }
/// Fork::Child => {
/// std::process::exit(42);
/// }
/// }
/// # std::io::Result::Ok(())
/// ```