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
50 explicit ExitEvent(int64_t code,
int sig) noexcept
51 : status{code}, signal{sig}
65 static void exitCallback(uv_process_t *handle, int64_t exitStatus,
int termSignal) {
67 process.publish(
ExitEvent{exitStatus, termSignal});
71 using Process = details::UVProcessFlags;
72 using StdIO = details::UVStdIOFlags;
74 ProcessHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref)
75 :
Handle{ca, std::move(ref)}, poFdStdio{1}
78 poFdStdio[0].flags =
static_cast<uv_stdio_flags
>(StdIO::IGNORE_STREAM);
96 uv_disable_stdio_inheritance();
105 static bool kill(
int pid,
int signum) noexcept {
106 return (0 == uv_kill(pid, signum));
133 void spawn(
const char *file,
char **args,
char **env =
nullptr) {
134 uv_process_options_t po;
136 po.exit_cb = &exitCallback;
141 po.cwd = poCwd.empty() ? nullptr : poCwd.data();
153 std::vector<uv_stdio_container_t> poStdio{poFdStdio.size() + poStreamStdio.size()};
154 poStdio.insert(poStdio.begin(), poStreamStdio.cbegin(), poStreamStdio.cend());
155 poStdio.insert(poStdio.begin(), poFdStdio.cbegin(), poFdStdio.cend());
156 po.stdio_count =
static_cast<decltype(po.stdio_count)
>(poStdio.size());
157 po.stdio = poStdio.data();
161 initialize([](
auto...){
return 0; });
163 invoke(&uv_spawn, parent(),
get(), &po);
171 invoke(&uv_process_kill,
get(), signum);
238 template<
typename T,
typename U>
240 uv_stdio_container_t container;
241 Flags<StdIO>::Type fgs = flags;
242 container.flags =
static_cast<uv_stdio_flags
>(fgs);
243 container.data.stream = get<uv_stream_t>(stream);
244 poStreamStdio.push_back(std::move(container));
274 auto fgs =
static_cast<uv_stdio_flags
>(Flags<StdIO>::Type{flags});
276 auto actual = FileHandle::Type{fd};
278 if(actual == FileHandle::Type{
StdIN}) {
279 poFdStdio[0].
flags = fgs;
281 auto it = std::find_if(poFdStdio.begin(), poFdStdio.end(), [actual](
auto &&container){
282 return container.data.fd == actual;
285 if(it == poFdStdio.cend()) {
286 uv_stdio_container_t container;
287 container.
flags = fgs;
288 container.data.fd = actual;
289 poFdStdio.push_back(std::move(container));
292 it->data.fd = actual;
322 std::vector<uv_stdio_container_t> poFdStdio;
323 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.