| 332 | } |
| 333 | |
| 334 | int SubProcess::Communicate(const string* stdin_input, string* stdout_output, |
| 335 | string* stderr_output) { |
| 336 | struct pollfd fds[kNFds]; |
| 337 | size_t nbytes[kNFds]; |
| 338 | string* iobufs[kNFds]; |
| 339 | int fd_count = 0; |
| 340 | |
| 341 | proc_mu_.lock(); |
| 342 | bool running = running_; |
| 343 | proc_mu_.unlock(); |
| 344 | if (!running) { |
| 345 | LOG(ERROR) << "Communicate called without a running process."; |
| 346 | return 1; |
| 347 | } |
| 348 | |
| 349 | // If SIGPIPE handling is the default action, change it to ignore SIGPIPE and |
| 350 | // keep it ignored, don't change it back. This is needed while communicating |
| 351 | // with the child process so the parent process can survive the death of the |
| 352 | // child process while it is writing to its stdin. If the application has |
| 353 | // registered a SIGPIPE handler, then let it deal with any signals generated |
| 354 | // by the premature death of the child process, don't overwrite its handler. |
| 355 | struct sigaction act; |
| 356 | if (sigaction(SIGPIPE, nullptr, &act) < 0) { |
| 357 | LOG(ERROR) << "Communicate cannot get SIGPIPE handler: " << strerror(errno); |
| 358 | return 1; |
| 359 | } |
| 360 | if (act.sa_handler == SIG_DFL) { |
| 361 | memset(&act, 0, sizeof(act)); |
| 362 | act.sa_handler = SIG_IGN; |
| 363 | sigemptyset(&act.sa_mask); |
| 364 | if (sigaction(SIGPIPE, &act, nullptr) < 0) { |
| 365 | LOG(ERROR) << "Communicate cannot ignore SIGPIPE: " << strerror(errno); |
| 366 | return 1; |
| 367 | } |
| 368 | } |
| 369 | |
| 370 | // Lock data_mu_ but not proc_mu_ while communicating with the child process |
| 371 | // in order for Kill() to be able to terminate the child from another thread. |
| 372 | data_mu_.lock(); |
| 373 | |
| 374 | // Initialize the poll() structures and buffer tracking. |
| 375 | for (int i = 0; i < kNFds; i++) { |
| 376 | if (action_[i] == ACTION_PIPE) { |
| 377 | switch (i) { |
| 378 | case CHAN_STDIN: |
| 379 | // Special case: if no data is given to send to the child process, |
| 380 | // close the pipe to unblock the child, and skip the file descriptor. |
| 381 | if (stdin_input == nullptr) { |
| 382 | close(parent_pipe_[i]); |
| 383 | parent_pipe_[i] = -1; |
| 384 | continue; |
| 385 | } |
| 386 | iobufs[fd_count] = const_cast<string*>(stdin_input); |
| 387 | break; |
| 388 | case CHAN_STDOUT: |
| 389 | iobufs[fd_count] = stdout_output; |
| 390 | break; |
| 391 | case CHAN_STDERR: |