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,
28 WINDOWS_HIDE_CONSOLE = UV_PROCESS_WINDOWS_HIDE_CONSOLE,
29 WINDOWS_HIDE_GUI = UV_PROCESS_WINDOWS_HIDE_GUI
33 enum class UVStdIOFlags: std::underlying_type_t<uv_stdio_flags> {
34 IGNORE_STREAM = UV_IGNORE,
35 CREATE_PIPE = UV_CREATE_PIPE,
36 INHERIT_FD = UV_INHERIT_FD,
37 INHERIT_STREAM = UV_INHERIT_STREAM,
38 READABLE_PIPE = UV_READABLE_PIPE,
39 WRITABLE_PIPE = UV_WRITABLE_PIPE,
40 OVERLAPPED_PIPE = UV_OVERLAPPED_PIPE
53 explicit ExitEvent(int64_t code,
int sig) noexcept
54 : status{code}, signal{sig}
68 static void exitCallback(uv_process_t *handle, int64_t exitStatus,
int termSignal) {
70 process.publish(
ExitEvent{exitStatus, termSignal});
74 using Process = details::UVProcessFlags;
75 using StdIO = details::UVStdIOFlags;
77 ProcessHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref)
78 :
Handle{ca, std::move(ref)}
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;
140 po.cwd = poCwd.empty() ? nullptr : poCwd.data();
145 std::vector<uv_stdio_container_t> poStdio;
146 poStdio.reserve(poFdStdio.size() + poStreamStdio.size());
147 poStdio.insert(poStdio.begin(), poFdStdio.cbegin(), poFdStdio.cend());
148 poStdio.insert(poStdio.end(), poStreamStdio.cbegin(), poStreamStdio.cend());
150 po.stdio_count =
static_cast<decltype(po.stdio_count)
>(poStdio.size());
151 po.stdio = poStdio.data();
155 initialize([](
auto...){
return 0; });
157 invoke(&uv_spawn, parent(),
get(), &po);
165 invoke(&uv_process_kill,
get(), signum);
235 template<
typename T,
typename U>
237 uv_stdio_container_t container;
238 Flags<StdIO>::Type fgs = flags;
239 container.flags =
static_cast<uv_stdio_flags
>(fgs);
240 container.data.stream = get<uv_stream_t>(stream);
241 poStreamStdio.push_back(std::move(container));
272 auto fgs =
static_cast<uv_stdio_flags
>(Flags<StdIO>::Type{flags});
274 auto actual = FileHandle::Type{fd};
276 auto it = std::find_if(poFdStdio.begin(), poFdStdio.end(), [actual](
auto &&container){
277 return container.data.fd == actual;
280 if(it == poFdStdio.cend()) {
281 uv_stdio_container_t container;
282 container.
flags = fgs;
283 container.data.fd = actual;
284 poFdStdio.push_back(std::move(container));
287 it->data.fd = actual;
316 std::vector<uv_stdio_container_t> poFdStdio;
317 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.
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.