We use sockets, not pipes, because fds are bidir. */
| 202 | |
| 203 | /* We use sockets, not pipes, because fds are bidir. */ |
| 204 | static int subd(const char *path, const char *name, |
| 205 | bool debugging, |
| 206 | int *msgfd, |
| 207 | bool io_logging, |
| 208 | bool trace_logging, |
| 209 | bool developer, |
| 210 | va_list *ap) |
| 211 | { |
| 212 | int childmsg[2], execfail[2]; |
| 213 | pid_t childpid; |
| 214 | int err, *fd; |
| 215 | |
| 216 | if (socketpair(AF_LOCAL, SOCK_STREAM, 0, childmsg) != 0) |
| 217 | goto fail; |
| 218 | |
| 219 | if (pipe(execfail) != 0) |
| 220 | goto close_msgfd_fail; |
| 221 | |
| 222 | if (fcntl(execfail[1], F_SETFD, fcntl(execfail[1], F_GETFD) |
| 223 | | FD_CLOEXEC) < 0) |
| 224 | goto close_execfail_fail; |
| 225 | |
| 226 | childpid = fork(); |
| 227 | if (childpid < 0) |
| 228 | goto close_execfail_fail; |
| 229 | |
| 230 | if (childpid == 0) { |
| 231 | size_t num_args; |
| 232 | char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL }; |
| 233 | int **fds = tal_arr(tmpctx, int *, 3); |
| 234 | int stdoutfd = STDOUT_FILENO, stderrfd = STDERR_FILENO; |
| 235 | |
| 236 | close(childmsg[0]); |
| 237 | close(execfail[0]); |
| 238 | |
| 239 | /* msg = STDIN (0) */ |
| 240 | fds[0] = &childmsg[1]; |
| 241 | /* These are untouched */ |
| 242 | fds[1] = &stdoutfd; |
| 243 | fds[2] = &stderrfd; |
| 244 | |
| 245 | while ((fd = va_arg(*ap, int *)) != NULL) { |
| 246 | assert(*fd != -1); |
| 247 | tal_arr_expand(&fds, fd); |
| 248 | } |
| 249 | |
| 250 | /* Finally, the fd to report exec errors on */ |
| 251 | tal_arr_expand(&fds, &execfail[1]); |
| 252 | |
| 253 | if (!shuffle_fds(fds, tal_count(fds))) |
| 254 | goto child_errno_fail; |
| 255 | |
| 256 | /* Make (fairly!) sure all other fds are closed. */ |
| 257 | closefrom(tal_count(fds)); |
| 258 | |
| 259 | num_args = 0; |
| 260 | args[num_args++] = tal_strdup(NULL, path); |
| 261 | if (io_logging) |
no test coverage detected