1/*
2 * Copyright 2012-present Facebook, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _GNU_SOURCE
18#define _GNU_SOURCE
19#endif
20
21#include <folly/Subprocess.h>
22
23#if __linux__
24#include <sys/prctl.h>
25#endif
26#include <fcntl.h>
27
28#include <algorithm>
29#include <array>
30#include <system_error>
31
32#include <boost/container/flat_set.hpp>
33#include <boost/range/adaptors.hpp>
34
35#include <glog/logging.h>
36
37#include <folly/Conv.h>
38#include <folly/Exception.h>
39#include <folly/ScopeGuard.h>
40#include <folly/String.h>
41#include <folly/io/Cursor.h>
42#include <folly/lang/Assume.h>
43#include <folly/portability/Sockets.h>
44#include <folly/portability/Stdlib.h>
45#include <folly/portability/SysSyscall.h>
46#include <folly/portability/Unistd.h>
47#include <folly/system/Shell.h>
48
49constexpr int kExecFailure = 127;
50constexpr int kChildFailure = 126;
51
52namespace folly {
53
54ProcessReturnCode ProcessReturnCode::make(int status) {
55 if (!WIFEXITED(status) && !WIFSIGNALED(status)) {
56 throw std::runtime_error(
57 to<std::string>("Invalid ProcessReturnCode: ", status));
58 }
59 return ProcessReturnCode(status);
60}
61
62ProcessReturnCode::ProcessReturnCode(ProcessReturnCode&& p) noexcept
63 : rawStatus_(p.rawStatus_) {
64 p.rawStatus_ = ProcessReturnCode::RV_NOT_STARTED;
65}
66
67ProcessReturnCode& ProcessReturnCode::operator=(
68 ProcessReturnCode&& p) noexcept {
69 rawStatus_ = p.rawStatus_;
70 p.rawStatus_ = ProcessReturnCode::RV_NOT_STARTED;
71 return *this;
72}
73
74ProcessReturnCode::State ProcessReturnCode::state() const {
75 if (rawStatus_ == RV_NOT_STARTED) {
76 return NOT_STARTED;
77 }
78 if (rawStatus_ == RV_RUNNING) {
79 return RUNNING;
80 }
81 if (WIFEXITED(rawStatus_)) {
82 return EXITED;
83 }
84 if (WIFSIGNALED(rawStatus_)) {
85 return KILLED;
86 }
87 assume_unreachable();
88}
89
90void ProcessReturnCode::enforce(State expected) const {
91 State s = state();
92 if (s != expected) {
93 throw std::logic_error(to<std::string>(
94 "Bad use of ProcessReturnCode; state is ", s, " expected ", expected));
95 }
96}
97
98int ProcessReturnCode::exitStatus() const {
99 enforce(EXITED);
100 return WEXITSTATUS(rawStatus_);
101}
102
103int ProcessReturnCode::killSignal() const {
104 enforce(KILLED);
105 return WTERMSIG(rawStatus_);
106}
107
108bool ProcessReturnCode::coreDumped() const {
109 enforce(KILLED);
110 return WCOREDUMP(rawStatus_);
111}
112
113std::string ProcessReturnCode::str() const {
114 switch (state()) {
115 case NOT_STARTED:
116 return "not started";
117 case RUNNING:
118 return "running";
119 case EXITED:
120 return to<std::string>("exited with status ", exitStatus());
121 case KILLED:
122 return to<std::string>(
123 "killed by signal ",
124 killSignal(),
125 (coreDumped() ? " (core dumped)" : ""));
126 }
127 assume_unreachable();
128}
129
130CalledProcessError::CalledProcessError(ProcessReturnCode rc)
131 : SubprocessError(rc.str()), returnCode_(rc) {}
132
133static inline std::string toSubprocessSpawnErrorMessage(
134 char const* executable,
135 int errCode,
136 int errnoValue) {
137 auto prefix = errCode == kExecFailure ? "failed to execute "
138 : "error preparing to execute ";
139 return to<std::string>(prefix, executable, ": ", errnoStr(errnoValue));
140}
141
142SubprocessSpawnError::SubprocessSpawnError(
143 const char* executable,
144 int errCode,
145 int errnoValue)
146 : SubprocessError(
147 toSubprocessSpawnErrorMessage(executable, errCode, errnoValue)),
148 errnoValue_(errnoValue) {}
149
150namespace {
151
152// Copy pointers to the given strings in a format suitable for posix_spawn
153std::unique_ptr<const char* []> cloneStrings(
154 const std::vector<std::string>& s) {
155 std::unique_ptr<const char*[]> d(new const char*[s.size() + 1]);
156 for (size_t i = 0; i < s.size(); i++) {
157 d[i] = s[i].c_str();
158 }
159 d[s.size()] = nullptr;
160 return d;
161}
162
163// Check a wait() status, throw on non-successful
164void checkStatus(ProcessReturnCode returnCode) {
165 if (returnCode.state() != ProcessReturnCode::EXITED ||
166 returnCode.exitStatus() != 0) {
167 throw CalledProcessError(returnCode);
168 }
169}
170
171} // namespace
172
173Subprocess::Options& Subprocess::Options::fd(int fd, int action) {
174 if (action == Subprocess::PIPE) {
175 if (fd == 0) {
176 action = Subprocess::PIPE_IN;
177 } else if (fd == 1 || fd == 2) {
178 action = Subprocess::PIPE_OUT;
179 } else {
180 throw std::invalid_argument(
181 to<std::string>("Only fds 0, 1, 2 are valid for action=PIPE: ", fd));
182 }
183 }
184 fdActions_[fd] = action;
185 return *this;
186}
187
188Subprocess::Subprocess() {}
189
190Subprocess::Subprocess(
191 const std::vector<std::string>& argv,
192 const Options& options,
193 const char* executable,
194 const std::vector<std::string>* env) {
195 if (argv.empty()) {
196 throw std::invalid_argument("argv must not be empty");
197 }
198 if (!executable) {
199 executable = argv[0].c_str();
200 }
201 spawn(cloneStrings(argv), executable, options, env);
202}
203
204Subprocess::Subprocess(
205 const std::string& cmd,
206 const Options& options,
207 const std::vector<std::string>* env) {
208 if (options.usePath_) {
209 throw std::invalid_argument("usePath() not allowed when running in shell");
210 }
211
212 std::vector<std::string> argv = {"/bin/sh", "-c", cmd};
213 spawn(cloneStrings(argv), argv[0].c_str(), options, env);
214}
215
216Subprocess::~Subprocess() {
217 CHECK_NE(returnCode_.state(), ProcessReturnCode::RUNNING)
218 << "Subprocess destroyed without reaping child";
219}
220
221namespace {
222
223struct ChildErrorInfo {
224 int errCode;
225 int errnoValue;
226};
227
228[[noreturn]] void childError(int errFd, int errCode, int errnoValue) {
229 ChildErrorInfo info = {errCode, errnoValue};
230 // Write the error information over the pipe to our parent process.
231 // We can't really do anything else if this write call fails.
232 writeNoInt(errFd, &info, sizeof(info));
233 // exit
234 _exit(errCode);
235}
236
237} // namespace
238
239void Subprocess::setAllNonBlocking() {
240 for (auto& p : pipes_) {
241 int fd = p.pipe.fd();
242 int flags = ::fcntl(fd, F_GETFL);
243 checkUnixError(flags, "fcntl");
244 int r = ::fcntl(fd, F_SETFL, flags | O_NONBLOCK);
245 checkUnixError(r, "fcntl");
246 }
247}
248
249void Subprocess::spawn(
250 std::unique_ptr<const char*[]> argv,
251 const char* executable,
252 const Options& optionsIn,
253 const std::vector<std::string>* env) {
254 if (optionsIn.usePath_ && env) {
255 throw std::invalid_argument(
256 "usePath() not allowed when overriding environment");
257 }
258
259 // Make a copy, we'll mutate options
260 Options options(optionsIn);
261
262 // On error, close all pipes_ (ignoring errors, but that seems fine here).
263 auto pipesGuard = makeGuard([this] { pipes_.clear(); });
264
265 // Create a pipe to use to receive error information from the child,
266 // in case it fails before calling exec()
267 int errFds[2];
268#if FOLLY_HAVE_PIPE2
269 checkUnixError(::pipe2(errFds, O_CLOEXEC), "pipe2");
270#else
271 checkUnixError(::pipe(errFds), "pipe");
272#endif
273 SCOPE_EXIT {
274 CHECK_ERR(::close(errFds[0]));
275 if (errFds[1] >= 0) {
276 CHECK_ERR(::close(errFds[1]));
277 }
278 };
279
280#if !FOLLY_HAVE_PIPE2
281 // Ask the child to close the read end of the error pipe.
282 checkUnixError(fcntl(errFds[0], F_SETFD, FD_CLOEXEC), "set FD_CLOEXEC");
283 // Set the close-on-exec flag on the write side of the pipe.
284 // This way the pipe will be closed automatically in the child if execve()
285 // succeeds. If the exec fails the child can write error information to the
286 // pipe.
287 checkUnixError(fcntl(errFds[1], F_SETFD, FD_CLOEXEC), "set FD_CLOEXEC");
288#endif
289
290 // Perform the actual work of setting up pipes then forking and
291 // executing the child.
292 spawnInternal(std::move(argv), executable, options, env, errFds[1]);
293
294 // After spawnInternal() returns the child is alive. We have to be very
295 // careful about throwing after this point. We are inside the constructor,
296 // so if we throw the Subprocess object will have never existed, and the
297 // destructor will never be called.
298 //
299 // We should only throw if we got an error via the errFd, and we know the
300 // child has exited and can be immediately waited for. In all other cases,
301 // we have no way of cleaning up the child.
302
303 // Close writable side of the errFd pipe in the parent process
304 CHECK_ERR(::close(errFds[1]));
305 errFds[1] = -1;
306
307 // Read from the errFd pipe, to tell if the child ran into any errors before
308 // calling exec()
309 readChildErrorPipe(errFds[0], executable);
310
311 // If we spawned a detached child, wait on the intermediate child process.
312 // It always exits immediately.
313 if (options.detach_) {
314 wait();
315 }
316
317 // We have fully succeeded now, so release the guard on pipes_
318 pipesGuard.dismiss();
319}
320
321// With -Wclobbered, gcc complains about vfork potentially cloberring the
322// childDir variable, even though we only use it on the child side of the
323// vfork.
324
325FOLLY_PUSH_WARNING
326FOLLY_GCC_DISABLE_WARNING("-Wclobbered")
327void Subprocess::spawnInternal(
328 std::unique_ptr<const char*[]> argv,
329 const char* executable,
330 Options& options,
331 const std::vector<std::string>* env,
332 int errFd) {
333 // Parent work, pre-fork: create pipes
334 std::vector<int> childFds;
335 // Close all of the childFds as we leave this scope
336 SCOPE_EXIT {
337 // These are only pipes, closing them shouldn't fail
338 for (int cfd : childFds) {
339 CHECK_ERR(::close(cfd));
340 }
341 };
342
343 int r;
344 for (auto& p : options.fdActions_) {
345 if (p.second == PIPE_IN || p.second == PIPE_OUT) {
346 int fds[2];
347 // We're setting both ends of the pipe as close-on-exec. The child
348 // doesn't need to reset the flag on its end, as we always dup2() the fd,
349 // and dup2() fds don't share the close-on-exec flag.
350#if FOLLY_HAVE_PIPE2
351 // If possible, set close-on-exec atomically. Otherwise, a concurrent
352 // Subprocess invocation can fork() between "pipe" and "fnctl",
353 // causing FDs to leak.
354 r = ::pipe2(fds, O_CLOEXEC);
355 checkUnixError(r, "pipe2");
356#else
357 r = ::pipe(fds);
358 checkUnixError(r, "pipe");
359 r = fcntl(fds[0], F_SETFD, FD_CLOEXEC);
360 checkUnixError(r, "set FD_CLOEXEC");
361 r = fcntl(fds[1], F_SETFD, FD_CLOEXEC);
362 checkUnixError(r, "set FD_CLOEXEC");
363#endif
364 pipes_.emplace_back();
365 Pipe& pipe = pipes_.back();
366 pipe.direction = p.second;
367 int cfd;
368 if (p.second == PIPE_IN) {
369 // Child gets reading end
370 pipe.pipe = folly::File(fds[1], /*ownsFd=*/true);
371 cfd = fds[0];
372 } else {
373 pipe.pipe = folly::File(fds[0], /*ownsFd=*/true);
374 cfd = fds[1];
375 }
376 p.second = cfd; // ensure it gets dup2()ed
377 pipe.childFd = p.first;
378 childFds.push_back(cfd);
379 }
380 }
381
382 // This should already be sorted, as options.fdActions_ is
383 DCHECK(std::is_sorted(pipes_.begin(), pipes_.end()));
384
385 // Note that the const casts below are legit, per
386 // http://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html
387
388 char** argVec = const_cast<char**>(argv.get());
389
390 // Set up environment
391 std::unique_ptr<const char*[]> envHolder;
392 char** envVec;
393 if (env) {
394 envHolder = cloneStrings(*env);
395 envVec = const_cast<char**>(envHolder.get());
396 } else {
397 envVec = environ;
398 }
399
400 // Block all signals around vfork; see http://ewontfix.com/7/.
401 //
402 // As the child may run in the same address space as the parent until
403 // the actual execve() system call, any (custom) signal handlers that
404 // the parent has might alter parent's memory if invoked in the child,
405 // with undefined results. So we block all signals in the parent before
406 // vfork(), which will cause them to be blocked in the child as well (we
407 // rely on the fact that Linux, just like all sane implementations, only
408 // clones the calling thread). Then, in the child, we reset all signals
409 // to their default dispositions (while still blocked), and unblock them
410 // (so the exec()ed process inherits the parent's signal mask)
411 //
412 // The parent also unblocks all signals as soon as vfork() returns.
413 sigset_t allBlocked;
414 r = sigfillset(&allBlocked);
415 checkUnixError(r, "sigfillset");
416 sigset_t oldSignals;
417
418 r = pthread_sigmask(SIG_SETMASK, &allBlocked, &oldSignals);
419 checkPosixError(r, "pthread_sigmask");
420 SCOPE_EXIT {
421 // Restore signal mask
422 r = pthread_sigmask(SIG_SETMASK, &oldSignals, nullptr);
423 CHECK_EQ(r, 0) << "pthread_sigmask: " << errnoStr(r); // shouldn't fail
424 };
425
426 // Call c_str() here, as it's not necessarily safe after fork.
427 const char* childDir =
428 options.childDir_.empty() ? nullptr : options.childDir_.c_str();
429
430 pid_t pid;
431#ifdef __linux__
432 if (options.cloneFlags_) {
433 pid = syscall(SYS_clone, *options.cloneFlags_, 0, nullptr, nullptr);
434 } else {
435#endif
436 if (options.detach_) {
437 // If we are detaching we must use fork() instead of vfork() for the first
438 // fork, since we aren't going to simply call exec() in the child.
439 pid = fork();
440 } else {
441 pid = vfork();
442 }
443#ifdef __linux__
444 }
445#endif
446 checkUnixError(pid, errno, "failed to fork");
447 if (pid == 0) {
448 // Fork a second time if detach_ was requested.
449 // This must be done before signals are restored in prepareChild()
450 if (options.detach_) {
451#ifdef __linux__
452 if (options.cloneFlags_) {
453 pid = syscall(SYS_clone, *options.cloneFlags_, 0, nullptr, nullptr);
454 } else {
455#endif
456 pid = vfork();
457#ifdef __linux__
458 }
459#endif
460 if (pid == -1) {
461 // Inform our parent process of the error so it can throw in the parent.
462 childError(errFd, kChildFailure, errno);
463 } else if (pid != 0) {
464 // We are the intermediate process. Exit immediately.
465 // Our child will still inform the original parent of success/failure
466 // through errFd. The pid of the grandchild process never gets
467 // propagated back up to the original parent. In the future we could
468 // potentially send it back using errFd if we needed to.
469 _exit(0);
470 }
471 }
472
473 int errnoValue = prepareChild(options, &oldSignals, childDir);
474 if (errnoValue != 0) {
475 childError(errFd, kChildFailure, errnoValue);
476 }
477
478 errnoValue = runChild(executable, argVec, envVec, options);
479 // If we get here, exec() failed.
480 childError(errFd, kExecFailure, errnoValue);
481 }
482
483 // Child is alive. We have to be very careful about throwing after this
484 // point. We are inside the constructor, so if we throw the Subprocess
485 // object will have never existed, and the destructor will never be called.
486 //
487 // We should only throw if we got an error via the errFd, and we know the
488 // child has exited and can be immediately waited for. In all other cases,
489 // we have no way of cleaning up the child.
490 pid_ = pid;
491 returnCode_ = ProcessReturnCode::makeRunning();
492}
493FOLLY_POP_WARNING
494
495int Subprocess::prepareChild(
496 const Options& options,
497 const sigset_t* sigmask,
498 const char* childDir) const {
499 // While all signals are blocked, we must reset their
500 // dispositions to default.
501 for (int sig = 1; sig < NSIG; ++sig) {
502 ::signal(sig, SIG_DFL);
503 }
504
505 {
506 // Unblock signals; restore signal mask.
507 int r = pthread_sigmask(SIG_SETMASK, sigmask, nullptr);
508 if (r != 0) {
509 return r; // pthread_sigmask() returns an errno value
510 }
511 }
512
513 // Change the working directory, if one is given
514 if (childDir) {
515 if (::chdir(childDir) == -1) {
516 return errno;
517 }
518 }
519
520 // We don't have to explicitly close the parent's end of all pipes,
521 // as they all have the FD_CLOEXEC flag set and will be closed at
522 // exec time.
523
524 // Close all fds that we're supposed to close.
525 for (auto& p : options.fdActions_) {
526 if (p.second == CLOSE) {
527 if (::close(p.first) == -1) {
528 return errno;
529 }
530 } else if (p.second != p.first) {
531 if (::dup2(p.second, p.first) == -1) {
532 return errno;
533 }
534 }
535 }
536
537 // If requested, close all other file descriptors. Don't close
538 // any fds in options.fdActions_, and don't touch stdin, stdout, stderr.
539 // Ignore errors.
540 if (options.closeOtherFds_) {
541 for (int fd = getdtablesize() - 1; fd >= 3; --fd) {
542 if (options.fdActions_.count(fd) == 0) {
543 ::close(fd);
544 }
545 }
546 }
547
548#if __linux__
549 // Opt to receive signal on parent death, if requested
550 if (options.parentDeathSignal_ != 0) {
551 const auto parentDeathSignal =
552 static_cast<unsigned long>(options.parentDeathSignal_);
553 if (prctl(PR_SET_PDEATHSIG, parentDeathSignal, 0, 0, 0) == -1) {
554 return errno;
555 }
556 }
557#endif
558
559 if (options.processGroupLeader_) {
560 if (setpgrp() == -1) {
561 return errno;
562 }
563 }
564
565 // The user callback comes last, so that the child is otherwise all set up.
566 if (options.dangerousPostForkPreExecCallback_) {
567 if (int error = (*options.dangerousPostForkPreExecCallback_)()) {
568 return error;
569 }
570 }
571
572 return 0;
573}
574
575int Subprocess::runChild(
576 const char* executable,
577 char** argv,
578 char** env,
579 const Options& options) const {
580 // Now, finally, exec.
581 if (options.usePath_) {
582 ::execvp(executable, argv);
583 } else {
584 ::execve(executable, argv, env);
585 }
586 return errno;
587}
588
589void Subprocess::readChildErrorPipe(int pfd, const char* executable) {
590 ChildErrorInfo info;
591 auto rc = readNoInt(pfd, &info, sizeof(info));
592 if (rc == 0) {
593 // No data means the child executed successfully, and the pipe
594 // was closed due to the close-on-exec flag being set.
595 return;
596 } else if (rc != sizeof(ChildErrorInfo)) {
597 // An error occurred trying to read from the pipe, or we got a partial read.
598 // Neither of these cases should really occur in practice.
599 //
600 // We can't get any error data from the child in this case, and we don't
601 // know if it is successfully running or not. All we can do is to return
602 // normally, as if the child executed successfully. If something bad
603 // happened the caller should at least get a non-normal exit status from
604 // the child.
605 LOG(ERROR) << "unexpected error trying to read from child error pipe "
606 << "rc=" << rc << ", errno=" << errno;
607 return;
608 }
609
610 // We got error data from the child. The child should exit immediately in
611 // this case, so wait on it to clean up.
612 wait();
613
614 // Throw to signal the error
615 throw SubprocessSpawnError(executable, info.errCode, info.errnoValue);
616}
617
618ProcessReturnCode Subprocess::poll(struct rusage* ru) {
619 returnCode_.enforce(ProcessReturnCode::RUNNING);
620 DCHECK_GT(pid_, 0);
621 int status;
622 pid_t found = ::wait4(pid_, &status, WNOHANG, ru);
623 // The spec guarantees that EINTR does not occur with WNOHANG, so the only
624 // two remaining errors are ECHILD (other code reaped the child?), or
625 // EINVAL (cosmic rays?), both of which merit an abort:
626 PCHECK(found != -1) << "waitpid(" << pid_ << ", &status, WNOHANG)";
627 if (found != 0) {
628 // Though the child process had quit, this call does not close the pipes
629 // since its descendants may still be using them.
630 returnCode_ = ProcessReturnCode::make(status);
631 pid_ = -1;
632 }
633 return returnCode_;
634}
635
636bool Subprocess::pollChecked() {
637 if (poll().state() == ProcessReturnCode::RUNNING) {
638 return false;
639 }
640 checkStatus(returnCode_);
641 return true;
642}
643
644ProcessReturnCode Subprocess::wait() {
645 returnCode_.enforce(ProcessReturnCode::RUNNING);
646 DCHECK_GT(pid_, 0);
647 int status;
648 pid_t found;
649 do {
650 found = ::waitpid(pid_, &status, 0);
651 } while (found == -1 && errno == EINTR);
652 // The only two remaining errors are ECHILD (other code reaped the
653 // child?), or EINVAL (cosmic rays?), and both merit an abort:
654 PCHECK(found != -1) << "waitpid(" << pid_ << ", &status, WNOHANG)";
655 // Though the child process had quit, this call does not close the pipes
656 // since its descendants may still be using them.
657 DCHECK_EQ(found, pid_);
658 returnCode_ = ProcessReturnCode::make(status);
659 pid_ = -1;
660 return returnCode_;
661}
662
663void Subprocess::waitChecked() {
664 wait();
665 checkStatus(returnCode_);
666}
667
668void Subprocess::sendSignal(int signal) {
669 returnCode_.enforce(ProcessReturnCode::RUNNING);
670 int r = ::kill(pid_, signal);
671 checkUnixError(r, "kill");
672}
673
674pid_t Subprocess::pid() const {
675 return pid_;
676}
677
678namespace {
679
680ByteRange queueFront(const IOBufQueue& queue) {
681 auto* p = queue.front();
682 if (!p) {
683 return ByteRange{};
684 }
685 return io::Cursor(p).peekBytes();
686}
687
688// fd write
689bool handleWrite(int fd, IOBufQueue& queue) {
690 for (;;) {
691 auto b = queueFront(queue);
692 if (b.empty()) {
693 return true; // EOF
694 }
695
696 ssize_t n = writeNoInt(fd, b.data(), b.size());
697 if (n == -1 && errno == EAGAIN) {
698 return false;
699 }
700 checkUnixError(n, "write");
701 queue.trimStart(n);
702 }
703}
704
705// fd read
706bool handleRead(int fd, IOBufQueue& queue) {
707 for (;;) {
708 auto p = queue.preallocate(100, 65000);
709 ssize_t n = readNoInt(fd, p.first, p.second);
710 if (n == -1 && errno == EAGAIN) {
711 return false;
712 }
713 checkUnixError(n, "read");
714 if (n == 0) {
715 return true;
716 }
717 queue.postallocate(n);
718 }
719}
720
721bool discardRead(int fd) {
722 static const size_t bufSize = 65000;
723 // Thread unsafe, but it doesn't matter.
724 static std::unique_ptr<char[]> buf(new char[bufSize]);
725
726 for (;;) {
727 ssize_t n = readNoInt(fd, buf.get(), bufSize);
728 if (n == -1 && errno == EAGAIN) {
729 return false;
730 }
731 checkUnixError(n, "read");
732 if (n == 0) {
733 return true;
734 }
735 }
736}
737
738} // namespace
739
740std::pair<std::string, std::string> Subprocess::communicate(StringPiece input) {
741 IOBufQueue inputQueue;
742 inputQueue.wrapBuffer(input.data(), input.size());
743
744 auto outQueues = communicateIOBuf(std::move(inputQueue));
745 auto outBufs =
746 std::make_pair(outQueues.first.move(), outQueues.second.move());
747 std::pair<std::string, std::string> out;
748 if (outBufs.first) {
749 outBufs.first->coalesce();
750 out.first.assign(
751 reinterpret_cast<const char*>(outBufs.first->data()),
752 outBufs.first->length());
753 }
754 if (outBufs.second) {
755 outBufs.second->coalesce();
756 out.second.assign(
757 reinterpret_cast<const char*>(outBufs.second->data()),
758 outBufs.second->length());
759 }
760 return out;
761}
762
763std::pair<IOBufQueue, IOBufQueue> Subprocess::communicateIOBuf(
764 IOBufQueue input) {
765 // If the user supplied a non-empty input buffer, make sure
766 // that stdin is a pipe so we can write the data.
767 if (!input.empty()) {
768 // findByChildFd() will throw std::invalid_argument if no pipe for
769 // STDIN_FILENO exists
770 findByChildFd(STDIN_FILENO);
771 }
772
773 std::pair<IOBufQueue, IOBufQueue> out;
774
775 auto readCallback = [&](int pfd, int cfd) -> bool {
776 if (cfd == STDOUT_FILENO) {
777 return handleRead(pfd, out.first);
778 } else if (cfd == STDERR_FILENO) {
779 return handleRead(pfd, out.second);
780 } else {
781 // Don't close the file descriptor, the child might not like SIGPIPE,
782 // just read and throw the data away.
783 return discardRead(pfd);
784 }
785 };
786
787 auto writeCallback = [&](int pfd, int cfd) -> bool {
788 if (cfd == STDIN_FILENO) {
789 return handleWrite(pfd, input);
790 } else {
791 // If we don't want to write to this fd, just close it.
792 return true;
793 }
794 };
795
796 communicate(std::move(readCallback), std::move(writeCallback));
797
798 return out;
799}
800
801void Subprocess::communicate(
802 FdCallback readCallback,
803 FdCallback writeCallback) {
804 // This serves to prevent wait() followed by communicate(), but if you
805 // legitimately need that, send a patch to delete this line.
806 returnCode_.enforce(ProcessReturnCode::RUNNING);
807 setAllNonBlocking();
808
809 std::vector<pollfd> fds;
810 fds.reserve(pipes_.size());
811 std::vector<size_t> toClose; // indexes into pipes_
812 toClose.reserve(pipes_.size());
813
814 while (!pipes_.empty()) {
815 fds.clear();
816 toClose.clear();
817
818 for (auto& p : pipes_) {
819 pollfd pfd;
820 pfd.fd = p.pipe.fd();
821 // Yes, backwards, PIPE_IN / PIPE_OUT are defined from the
822 // child's point of view.
823 if (!p.enabled) {
824 // Still keeping fd in watched set so we get notified of POLLHUP /
825 // POLLERR
826 pfd.events = 0;
827 } else if (p.direction == PIPE_IN) {
828 pfd.events = POLLOUT;
829 } else {
830 pfd.events = POLLIN;
831 }
832 fds.push_back(pfd);
833 }
834
835 int r;
836 do {
837 r = ::poll(fds.data(), fds.size(), -1);
838 } while (r == -1 && errno == EINTR);
839 checkUnixError(r, "poll");
840
841 for (size_t i = 0; i < pipes_.size(); ++i) {
842 auto& p = pipes_[i];
843 auto parentFd = p.pipe.fd();
844 DCHECK_EQ(fds[i].fd, parentFd);
845 short events = fds[i].revents;
846
847 bool closed = false;
848 if (events & POLLOUT) {
849 DCHECK(!(events & POLLIN));
850 if (writeCallback(parentFd, p.childFd)) {
851 toClose.push_back(i);
852 closed = true;
853 }
854 }
855
856 // Call read callback on POLLHUP, to give it a chance to read (and act
857 // on) end of file
858 if (events & (POLLIN | POLLHUP)) {
859 DCHECK(!(events & POLLOUT));
860 if (readCallback(parentFd, p.childFd)) {
861 toClose.push_back(i);
862 closed = true;
863 }
864 }
865
866 if ((events & (POLLHUP | POLLERR)) && !closed) {
867 toClose.push_back(i);
868 closed = true;
869 }
870 }
871
872 // Close the fds in reverse order so the indexes hold after erase()
873 for (int idx : boost::adaptors::reverse(toClose)) {
874 auto pos = pipes_.begin() + idx;
875 pos->pipe.close(); // Throws on error
876 pipes_.erase(pos);
877 }
878 }
879}
880
881void Subprocess::enableNotifications(int childFd, bool enabled) {
882 pipes_[findByChildFd(childFd)].enabled = enabled;
883}
884
885bool Subprocess::notificationsEnabled(int childFd) const {
886 return pipes_[findByChildFd(childFd)].enabled;
887}
888
889size_t Subprocess::findByChildFd(int childFd) const {
890 auto pos = std::lower_bound(
891 pipes_.begin(), pipes_.end(), childFd, [](const Pipe& pipe, int fd) {
892 return pipe.childFd < fd;
893 });
894 if (pos == pipes_.end() || pos->childFd != childFd) {
895 throw std::invalid_argument(
896 folly::to<std::string>("child fd not found ", childFd));
897 }
898 return pos - pipes_.begin();
899}
900
901void Subprocess::closeParentFd(int childFd) {
902 int idx = findByChildFd(childFd);
903 pipes_[idx].pipe.close(); // May throw
904 pipes_.erase(pipes_.begin() + idx);
905}
906
907std::vector<Subprocess::ChildPipe> Subprocess::takeOwnershipOfPipes() {
908 std::vector<Subprocess::ChildPipe> pipes;
909 for (auto& p : pipes_) {
910 pipes.emplace_back(p.childFd, std::move(p.pipe));
911 }
912 // release memory
913 std::vector<Pipe>().swap(pipes_);
914 return pipes;
915}
916
917namespace {
918
919class Initializer {
920 public:
921 Initializer() {
922 // We like EPIPE, thanks.
923 ::signal(SIGPIPE, SIG_IGN);
924 }
925};
926
927Initializer initializer;
928
929} // namespace
930
931} // namespace folly
932