The main entry of the child process. NOTE: This function has to be async signal safe.
| 214 | // |
| 215 | // NOTE: This function has to be async signal safe. |
| 216 | inline int childMain( |
| 217 | const std::string& path, |
| 218 | char** argv, |
| 219 | char** envp, |
| 220 | const InputFileDescriptors& stdinfds, |
| 221 | const OutputFileDescriptors& stdoutfds, |
| 222 | const OutputFileDescriptors& stderrfds, |
| 223 | const std::vector<int_fd>& whitelist_fds, |
| 224 | bool blocking, |
| 225 | int pipes[2], |
| 226 | const std::vector<Subprocess::ChildHook>& child_hooks) |
| 227 | { |
| 228 | // Close parent's end of the pipes. |
| 229 | if (stdinfds.write.isSome()) { |
| 230 | ::close(stdinfds.write.get()); |
| 231 | } |
| 232 | if (stdoutfds.read.isSome()) { |
| 233 | ::close(stdoutfds.read.get()); |
| 234 | } |
| 235 | if (stderrfds.read.isSome()) { |
| 236 | ::close(stderrfds.read.get()); |
| 237 | } |
| 238 | |
| 239 | // Currently we will block the child's execution of the new process |
| 240 | // until all the parent hooks (if any) have executed. |
| 241 | if (blocking) { |
| 242 | ::close(pipes[1]); |
| 243 | } |
| 244 | |
| 245 | // Redirect I/O for stdin/stdout/stderr. |
| 246 | while (::dup2(stdinfds.read, STDIN_FILENO) == -1 && errno == EINTR); |
| 247 | while (::dup2(stdoutfds.write, STDOUT_FILENO) == -1 && errno == EINTR); |
| 248 | while (::dup2(stderrfds.write, STDERR_FILENO) == -1 && errno == EINTR); |
| 249 | |
| 250 | // Close the copies. We need to make sure that we do not close the |
| 251 | // file descriptor assigned to stdin/stdout/stderr in case the |
| 252 | // parent has closed stdin/stdout/stderr when calling this |
| 253 | // function (in that case, a dup'ed file descriptor may have the |
| 254 | // same file descriptor number as stdin/stdout/stderr). |
| 255 | // |
| 256 | // We also need to ensure that we don't "double close" any file |
| 257 | // descriptors in the case where one of stdinfds.read, |
| 258 | // stdoutfds.write, or stdoutfds.write are equal. |
| 259 | if (stdinfds.read != STDIN_FILENO && |
| 260 | stdinfds.read != STDOUT_FILENO && |
| 261 | stdinfds.read != STDERR_FILENO) { |
| 262 | ::close(stdinfds.read); |
| 263 | } |
| 264 | if (stdoutfds.write != STDIN_FILENO && |
| 265 | stdoutfds.write != STDOUT_FILENO && |
| 266 | stdoutfds.write != STDERR_FILENO && |
| 267 | stdoutfds.write != stdinfds.read) { |
| 268 | ::close(stdoutfds.write); |
| 269 | } |
| 270 | if (stderrfds.write != STDIN_FILENO && |
| 271 | stderrfds.write != STDOUT_FILENO && |
| 272 | stderrfds.write != STDERR_FILENO && |
| 273 | stderrfds.write != stdinfds.read && |
nothing calls this directly
no test coverage detected