14 #include <unordered_map> 17 #include <cereal/archives/binary.hpp> 25 template <
class Archive>
27 archive(key, value, overwrite);
37 std::string
const& name,
38 std::string
const&
value,
40 char*
const*
const getEnv();
43 std::unordered_map<std::string, std::string> environ_;
44 char** env_ =
nullptr;
85 static void startForkServer();
86 static void endForkServer();
91 std::tuple<int, int, int> execute(
92 std::vector<std::string>
const& command,
93 std::vector<EnvVar>
const& env);
107 template <
typename F,
typename... Args>
108 int fork(F&& f, Args&&... args) {
110 std::is_trivially_copyable<F>::value,
"f must be trivially copyable!");
111 std::lock_guard<std::mutex> lock(mutex_);
112 std::stringstream oss;
113 cereal::BinaryOutputArchive ar(oss);
114 std::vector<int> (*ptrReadFds)(
int sock) = &forkReadFds<F, Args...>;
115 ar.saveBinary(&ptrReadFds,
sizeof(ptrReadFds));
116 void (*ptr)(cereal::BinaryInputArchive & ar,
const std::vector<int>& fds) =
117 &forkEntry<F, Args...>;
118 ar.saveBinary(&ptr,
sizeof(ptr));
119 ar.saveBinary(&f,
sizeof(f));
120 forkSerialize(ar, std::forward<Args>(args)...);
121 return forkSendCommand(oss.str());
126 int waitpid(
int pid);
130 int forkServerRFd_ = -1;
131 int forkServerWFd_ = -1;
132 int forkServerSock_ = -1;
134 static void sendfd(
int sock,
int fd);
135 static int recvfd(
int sock);
137 int forkSendCommand(
const std::string& data);
139 template <
typename T>
140 void forkSerialize(T& ar) {}
141 template <
typename T,
typename A,
typename... Args>
142 void forkSerialize(T& ar, A&& a, Args&&... args) {
143 ar(std::forward<A>(a));
144 forkSerialize(ar, std::forward<Args>(args)...);
146 template <
typename T,
typename... Args>
148 sendfd(forkServerSock_, (
int)fd);
149 forkSerialize(ar, std::forward<Args>(args)...);
152 template <
typename T>
153 struct typeResolver {};
155 template <
typename T>
156 static T forkDeserialize(
158 cereal::BinaryInputArchive& ar,
159 const std::vector<int>& fds,
165 static int forkDeserialize(
166 typeResolver<FileDescriptor>,
167 cereal::BinaryInputArchive& ar,
168 const std::vector<int>& fds,
170 return fds.at(fdsIndex++);
173 template <
typename T>
175 forkDeserializeFds(typeResolver<T>,
int sock, std::vector<int>& result) {
178 static int forkDeserializeFds(
179 typeResolver<FileDescriptor>,
181 std::vector<int>& result) {
182 result.push_back(
recvfd(sock));
186 template <
typename F,
typename... Args>
187 static std::vector<int> forkReadFds(
int sock) {
191 forkDeserializeFds(typeResolver<std::decay_t<Args>>{}, sock, r)...};
196 template <
typename F,
typename Tuple,
size_t... I>
197 static void applyImpl(F&& f, Tuple tuple, std::index_sequence<I...>) {
198 std::forward<F>(f)(std::move(std::get<I>(tuple))...);
201 template <
typename F,
typename Tuple>
202 static void apply(F&& f, Tuple tuple) {
206 std::make_index_sequence<std::tuple_size<Tuple>::value>{});
209 template <
typename F,
typename... Args>
210 static void forkEntry(
211 cereal::BinaryInputArchive& ar,
212 const std::vector<int>& fds) {
213 typename std::aligned_storage<sizeof(F), alignof(F)>::type buf;
214 ar.loadBinary(&buf,
sizeof(buf));
219 std::tuple<std::decay_t<Args>...>{forkDeserialize(
220 typeResolver<std::decay_t<Args>>{}, ar, fds, fdsIndex)...});
std::string value
Definition: forkserver.h:23
void serialize(Archive &archive)
Definition: forkserver.h:26
FileDescriptor(int fd)
Definition: forkserver.h:56
Definition: forkserver.h:31
This class lets us fork when using MPI.
Definition: forkserver.h:79
Definition: forkserver.h:21
File descriptors passed as arguments to ForkServer::fork must be wrapped in this class.
Definition: forkserver.h:54
int fork(F &&f, Args &&...args)
fork and call f with the specified arguments.
Definition: forkserver.h:108
std::string key
Definition: forkserver.h:22
int recvfd(int socket)
Definition: forkserver.cpp:157
Main namespace for bot-related code.
Definition: areainfo.cpp:17
bool overwrite
Definition: forkserver.h:24
void sendfd(int socket, int fd)
Definition: forkserver.cpp:127