/*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* make sure to serialize your signals (i.e. kill()) with the waits --
* either wait & signal from the same thread, or use a mutex.
*/
-#ifndef FOLLY_SUBPROCESS_H_
-#define FOLLY_SUBPROCESS_H_
+
+#pragma once
#include <sys/types.h>
#include <signal.h>
#include <boost/container/flat_map.hpp>
#include <boost/operators.hpp>
+#include <folly/Exception.h>
#include <folly/File.h>
#include <folly/FileUtil.h>
+#include <folly/Function.h>
#include <folly/gen/String.h>
#include <folly/io/IOBufQueue.h>
#include <folly/MapUtil.h>
Subprocess(Subprocess&&) = default;
Subprocess& operator=(Subprocess&&) = default;
+ /**
+ * Create an uninitialized subprocess.
+ *
+ * In this state it can only be destroyed, or assigned to using the move
+ * assignment operator.
+ */
+ Subprocess();
+
/**
* Create a subprocess from the given arguments. argv[0] must be listed.
* If not-null, executable must be the actual executable
* The shell to use is taken from the environment variable $SHELL,
* or /bin/sh if $SHELL is unset.
*/
+ FOLLY_DEPRECATED("Prefer not running in a shell or use `shellify`.")
explicit Subprocess(
const std::string& cmd,
const Options& options = Options(),
* expensive implementation choice, in order to make closeParentFd()
* thread-safe.
*/
- typedef std::function<bool(int, int)> FdCallback;
+ using FdCallback = folly::Function<bool(int, int)>;
void communicate(FdCallback readCallback, FdCallback writeCallback);
/**
* descriptors. Use the readLinesCallback() helper to get template
* deduction. For example:
*
- * auto read_cb = Subprocess::readLinesCallback(
- * [](int fd, folly::StringPiece s) {
- * std::cout << fd << " said: " << s;
- * return false; // Keep reading from the child
- * }
- * );
* subprocess.communicate(
- * // ReadLinesCallback contains StreamSplitter contains IOBuf, making
- * // it noncopyable, whereas std::function must be copyable. So, we
- * // keep the callback in a local, and instead pass a reference.
- * std::ref(read_cb),
+ * Subprocess::readLinesCallback(
+ * [](int fd, folly::StringPiece s) {
+ * std::cout << fd << " said: " << s;
+ * return false; // Keep reading from the child
+ * }
+ * ),
* [](int pdf, int cfd){ return true; } // Don't write to the child
* );
*
uint64_t maxLineLength = 0, // No line length limit by default
char delimiter = '\n',
uint64_t bufSize = 1024
- ) : fdLineCb_(std::move(fdLineCb)),
+ ) : fdLineCb_(std::forward<Callback>(fdLineCb)),
maxLineLength_(maxLineLength),
delimiter_(delimiter),
bufSize_(bufSize) {}
if (ret == -1 && errno == EAGAIN) { // No more data for now
return false;
}
+ checkUnixError(ret, "read");
if (ret == 0) { // Reached end-of-file
splitter.flush(); // Ignore return since the file is over anyway
return true;
// Helper to enable template deduction
template <class Callback>
- static ReadLinesCallback<Callback> readLinesCallback(
+ static auto readLinesCallback(
Callback&& fdLineCb,
- uint64_t maxLineLength = 0, // No line length limit by default
+ uint64_t maxLineLength = 0, // No line length limit by default
char delimiter = '\n',
- uint64_t bufSize = 1024) {
- return ReadLinesCallback<Callback>(
- std::move(fdLineCb), maxLineLength, delimiter, bufSize
- );
+ uint64_t bufSize = 1024)
+ -> ReadLinesCallback<typename std::decay<Callback>::type> {
+ return ReadLinesCallback<typename std::decay<Callback>::type>(
+ std::forward<Callback>(fdLineCb), maxLineLength, delimiter, bufSize);
}
/**
// Returns an index into pipes_. Throws std::invalid_argument if not found.
size_t findByChildFd(const int childFd) const;
-
- pid_t pid_;
- ProcessReturnCode returnCode_;
+ pid_t pid_{-1};
+ ProcessReturnCode returnCode_{RV_NOT_STARTED};
/**
* Represents a pipe between this process, and the child process (or its
}
} // namespace folly
-
-#endif /* FOLLY_SUBPROCESS_H_ */