22 enum class UVProcessFlags: std::underlying_type_t<uv_process_flags> {
23 SETUID = UV_PROCESS_SETUID,
24 SETGID = UV_PROCESS_SETGID,
25 WINDOWS_VERBATIM_ARGUMENTS = UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS,
26 DETACHED = UV_PROCESS_DETACHED,
27 WINDOWS_HIDE = UV_PROCESS_WINDOWS_HIDE
31 enum class UVStdIOFlags: std::underlying_type_t<uv_stdio_flags> {
32 IGNORE_STREAM = UV_IGNORE,
33 CREATE_PIPE = UV_CREATE_PIPE,
34 INHERIT_FD = UV_INHERIT_FD,
35 INHERIT_STREAM = UV_INHERIT_STREAM,
36 READABLE_PIPE = UV_READABLE_PIPE,
37 WRITABLE_PIPE = UV_WRITABLE_PIPE,
38 OVERLAPPED_PIPE = UV_OVERLAPPED_PIPE
51 explicit ExitEvent(int64_t code,
int sig) noexcept
52 : status{code}, signal{sig}
66 static void exitCallback(uv_process_t *handle, int64_t exitStatus,
int termSignal) {
68 process.publish(
ExitEvent{exitStatus, termSignal});
72 using Process = details::UVProcessFlags;
73 using StdIO = details::UVStdIOFlags;
75 ProcessHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref)
76 :
Handle{ca, std::move(ref)}, poFdStdio{1}
79 poFdStdio[0].flags =
static_cast<uv_stdio_flags
>(StdIO::IGNORE_STREAM);
97 uv_disable_stdio_inheritance();
106 static bool kill(
int pid,
int signum) noexcept {
107 return (0 == uv_kill(pid, signum));
134 void spawn(
const char *file,
char **args,
char **env =
nullptr) {
135 uv_process_options_t po;
137 po.exit_cb = &exitCallback;
142 po.cwd = poCwd.empty() ? nullptr : poCwd.data();
154 std::vector<uv_stdio_container_t> poStdio;
155 poStdio.reserve(poFdStdio.size() + poStreamStdio.size());
156 poStdio.insert(poStdio.begin(), poFdStdio.cbegin(), poFdStdio.cend());
157 poStdio.insert(poStdio.end(), poStreamStdio.cbegin(), poStreamStdio.cend());
159 po.stdio_count =
static_cast<decltype(po.stdio_count)
>(poStdio.size());
160 po.stdio = poStdio.data();
164 initialize([](
auto...){
return 0; });
166 invoke(&uv_spawn, parent(),
get(), &po);
174 invoke(&uv_process_kill,
get(), signum);
242 template<
typename T,
typename U>
244 uv_stdio_container_t container;
245 Flags<StdIO>::Type fgs = flags;
246 container.flags =
static_cast<uv_stdio_flags
>(fgs);
247 container.data.stream = get<uv_stream_t>(stream);
248 poStreamStdio.push_back(std::move(container));
279 auto fgs =
static_cast<uv_stdio_flags
>(Flags<StdIO>::Type{flags});
281 auto actual = FileHandle::Type{fd};
283 if(actual == FileHandle::Type{
StdIN}) {
284 poFdStdio[0].
flags = fgs;
286 auto it = std::find_if(poFdStdio.begin(), poFdStdio.end(), [actual](
auto &&container){
287 return container.data.fd == actual;
290 if(it == poFdStdio.cend()) {
291 uv_stdio_container_t container;
292 container.
flags = fgs;
293 container.data.fd = actual;
294 poFdStdio.push_back(std::move(container));
297 it->data.fd = actual;
327 std::vector<uv_stdio_container_t> poFdStdio;
328 std::vector<uv_stdio_container_t> poStreamStdio;
ProcessHandle & stdio(FileHandle fd, Flags< StdIO > flags)
Makes a file descriptor available to the child process.
ProcessHandle & cwd(std::string path) noexcept
Sets the current working directory for the subprocess.
details::UVTypeWrapper< uv_file > FileHandle
bool init()
Initializes the handle.
void spawn(const char *file, char **args, char **env=nullptr)
spawn Starts the process.
constexpr FileHandle StdIN
ProcessHandle & stdio(StreamHandle< T, U > &stream, Flags< StdIO > flags)
Makes a stdio handle available to the child process.
static void disableStdIOInheritance() noexcept
Disables inheritance for file descriptors/handles.
The ProcessHandle handle.
int pid() noexcept
Gets the PID of the spawned process.
ProcessHandle & flags(Flags< Process > flags) noexcept
Sets flags that control how spawn() behaves.
static bool kill(int pid, int signum) noexcept
kill Sends the specified signal to the given PID.
ProcessHandle & uid(Uid id)
Sets the child process' user id.
ProcessHandle & gid(Gid id)
Sets the child process' group id.
void kill(int signum)
Sends the specified signal to the internal process handle.