WPILibC++ 2023.4.3-108-ge5452e3
Process.h
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#ifndef WPINET_UV_PROCESS_H_
6#define WPINET_UV_PROCESS_H_
7
8#include <uv.h>
9
10#include <initializer_list>
11#include <memory>
12#include <span>
13#include <string>
14#include <string_view>
15
16#include <wpi/Signal.h>
17#include <wpi/SmallVector.h>
18
19#include "wpinet/uv/Handle.h"
20
21namespace wpi::uv {
22
23class Loop;
24class Pipe;
25
26/**
27 * Process handle.
28 * Process handles will spawn a new process and allow the user to control it
29 * and establish communication channels with it using streams.
30 */
31class Process final : public HandleImpl<Process, uv_process_t> {
32 struct private_init {};
33
34 public:
35 explicit Process(const private_init&) {}
36 ~Process() noexcept override = default;
37
38 /**
39 * Structure for Spawn() option temporaries. This is a reference type, so if
40 * this value is stored outside of a temporary, be careful about overwriting
41 * what it points to.
42 */
43 struct Option {
44 enum Type {
56 kStdioCreatePipe
57 };
58
59 Option() : m_type(kNone) {}
60
61 /*implicit*/ Option(const char* arg) { // NOLINT
62 m_data.str = arg;
63 }
64
65 /*implicit*/ Option(const std::string& arg) { // NOLINT
66 m_data.str = arg.data();
67 }
68
69 /*implicit*/ Option(std::string_view arg) // NOLINT
70 : m_strData(arg) {
71 m_data.str = m_strData.c_str();
72 }
73
74 /*implicit*/ Option(const SmallVectorImpl<char>& arg) // NOLINT
75 : m_strData(arg.data(), arg.size()) {
76 m_data.str = m_strData.c_str();
77 }
78
79 explicit Option(Type type) : m_type(type) {}
80
81 Type m_type = kArg;
82 std::string m_strData;
83 union {
84 const char* str;
87 unsigned int flags;
88 struct {
89 size_t index;
90 union {
91 int fd;
93 };
94 unsigned int flags;
95 } stdio;
96 } m_data;
97 };
98
99 /**
100 * Set environment variable for the subprocess. If not set, the parent's
101 * environment is used.
102 * @param env environment variable
103 */
106 o.m_strData = env;
107 o.m_data.str = o.m_strData.c_str();
108 return o;
109 }
110
111 /**
112 * Set the current working directory for the subprocess.
113 * @param cwd current working directory
114 */
117 o.m_strData = cwd;
118 o.m_data.str = o.m_strData.c_str();
119 return o;
120 }
121
122 /**
123 * Set the child process' user id.
124 * @param uid user id
125 */
126 static Option Uid(uv_uid_t uid) {
128 o.m_data.uid = uid;
129 return o;
130 }
131
132 /**
133 * Set the child process' group id.
134 * @param gid group id
135 */
136 static Option Gid(uv_gid_t gid) {
138 o.m_data.gid = gid;
139 return o;
140 }
141
142 /**
143 * Set spawn flags.
144 * @param flags Bitmask values from uv_process_flags.
145 */
146 static Option SetFlags(unsigned int flags) {
148 o.m_data.flags = flags;
149 return o;
150 }
151
152 /**
153 * Clear spawn flags.
154 * @param flags Bitmask values from uv_process_flags.
155 */
156 static Option ClearFlags(unsigned int flags) {
158 o.m_data.flags = flags;
159 return o;
160 }
161
162 /**
163 * Explicitly ignore a stdio.
164 * @param index stdio index
165 */
166 static Option StdioIgnore(size_t index) {
169 return o;
170 }
171
172 /**
173 * Inherit a file descriptor from the parent process.
174 * @param index stdio index
175 * @param fd parent file descriptor
176 */
177 static Option StdioInherit(size_t index, int fd) {
180 o.m_data.stdio.fd = fd;
181 return o;
182 }
183
184 /**
185 * Inherit a pipe from the parent process.
186 * @param index stdio index
187 * @param pipe pipe
188 */
189 static Option StdioInherit(size_t index, Pipe& pipe) {
192 o.m_data.stdio.pipe = &pipe;
193 return o;
194 }
195
196 /**
197 * Create a pipe between the child and the parent.
198 * @param index stdio index
199 * @param pipe pipe
200 * @param flags Some combination of UV_READABLE_PIPE, UV_WRITABLE_PIPE, and
201 * UV_OVERLAPPED_PIPE (Windows only, ignored on Unix).
202 */
203 static Option StdioCreatePipe(size_t index, Pipe& pipe, unsigned int flags) {
206 o.m_data.stdio.pipe = &pipe;
208 return o;
209 }
210
211 /**
212 * Disables inheritance for file descriptors / handles that this process
213 * inherited from its parent. The effect is that child processes spawned
214 * by this process don't accidentally inherit these handles.
215 *
216 * It is recommended to call this function as early in your program as
217 * possible, before the inherited file descriptors can be closed or
218 * duplicated.
219 */
221
222 /**
223 * Starts a process. If the process is not successfully spawned, an error
224 * is generated on the loop and this function returns nullptr.
225 *
226 * Possible reasons for failing to spawn would include (but not be limited to)
227 * the file to execute not existing, not having permissions to use the setuid
228 * or setgid specified, or not having enough memory to allocate for the new
229 * process.
230 *
231 * @param loop Loop object where this handle runs.
232 * @param file Path pointing to the program to be executed
233 * @param options Process options
234 */
235 static std::shared_ptr<Process> SpawnArray(Loop& loop, std::string_view file,
236 std::span<const Option> options);
237
238 static std::shared_ptr<Process> SpawnArray(
240 std::initializer_list<Option> options) {
241 return SpawnArray(loop, file, {options.begin(), options.end()});
242 }
243
244 template <typename... Args>
245 static std::shared_ptr<Process> Spawn(Loop& loop, std::string_view file,
246 const Args&... options) {
247 return SpawnArray(loop, file, {options...});
248 }
249
250 /**
251 * Starts a process. If the process is not successfully spawned, an error
252 * is generated on the loop and this function returns nullptr.
253 *
254 * Possible reasons for failing to spawn would include (but not be limited to)
255 * the file to execute not existing, not having permissions to use the setuid
256 * or setgid specified, or not having enough memory to allocate for the new
257 * process.
258 *
259 * @param loop Loop object where this handle runs.
260 * @param file Path pointing to the program to be executed
261 * @param options Process options
262 */
263 static std::shared_ptr<Process> SpawnArray(const std::shared_ptr<Loop>& loop,
265 std::span<const Option> options) {
266 return SpawnArray(*loop, file, options);
267 }
268
269 static std::shared_ptr<Process> SpawnArray(
270 const std::shared_ptr<Loop>& loop, std::string_view file,
271 std::initializer_list<Option> options) {
272 return SpawnArray(*loop, file, options);
273 }
274
275 template <typename... Args>
276 static std::shared_ptr<Process> Spawn(const std::shared_ptr<Loop>& loop,
278 const Args&... options) {
279 return SpawnArray(*loop, file, {options...});
280 }
281
282 /**
283 * Sends the specified signal to the process.
284 * @param signum signal number
285 */
286 void Kill(int signum) { Invoke(&uv_process_kill, GetRaw(), signum); }
287
288 /**
289 * Sends the specified signal to the given PID.
290 * @param pid process ID
291 * @param signum signal number
292 * @return 0 on success, otherwise error code.
293 */
294 static int Kill(int pid, int signum) noexcept { return uv_kill(pid, signum); }
295
296 /**
297 * Get the process ID.
298 * @return Process ID.
299 */
300 uv_pid_t GetPid() const noexcept { return GetRaw()->pid; }
301
302 /**
303 * Signal generated when the process exits. The parameters are the exit
304 * status and the signal that caused the process to terminate, if any.
305 */
307};
308
309} // namespace wpi::uv
310
311#endif // WPINET_UV_PROCESS_H_
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const ArgReturnType arg() const
Definition: ArrayCwiseUnaryOps.h:66
This file defines the SmallVector class.
then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file
Definition: ThirdPartyNotices.txt:192
SignalBase is an implementation of the observer pattern, through the use of an emitting object and sl...
Definition: Signal.h:495
bool Invoke(F &&f, Args &&... args) const
Definition: Handle.h:251
Handle.
Definition: Handle.h:273
uv_process_t * GetRaw() const noexcept
Get the underlying handle data structure.
Definition: Handle.h:288
Event loop.
Definition: Loop.h:37
Pipe handle.
Definition: Pipe.h:27
Process handle.
Definition: Process.h:31
static Option StdioCreatePipe(size_t index, Pipe &pipe, unsigned int flags)
Create a pipe between the child and the parent.
Definition: Process.h:203
static std::shared_ptr< Process > Spawn(Loop &loop, std::string_view file, const Args &... options)
Definition: Process.h:245
static Option StdioIgnore(size_t index)
Explicitly ignore a stdio.
Definition: Process.h:166
uv_pid_t GetPid() const noexcept
Get the process ID.
Definition: Process.h:300
static std::shared_ptr< Process > SpawnArray(const std::shared_ptr< Loop > &loop, std::string_view file, std::initializer_list< Option > options)
Definition: Process.h:269
static Option SetFlags(unsigned int flags)
Set spawn flags.
Definition: Process.h:146
static std::shared_ptr< Process > SpawnArray(const std::shared_ptr< Loop > &loop, std::string_view file, std::span< const Option > options)
Starts a process.
Definition: Process.h:263
static Option Env(std::string_view env)
Set environment variable for the subprocess.
Definition: Process.h:104
sig::Signal< int64_t, int > exited
Signal generated when the process exits.
Definition: Process.h:306
static int Kill(int pid, int signum) noexcept
Sends the specified signal to the given PID.
Definition: Process.h:294
static std::shared_ptr< Process > SpawnArray(Loop &loop, std::string_view file, std::initializer_list< Option > options)
Definition: Process.h:238
static void DisableStdioInheritance()
Disables inheritance for file descriptors / handles that this process inherited from its parent.
Definition: Process.h:220
static Option Cwd(std::string_view cwd)
Set the current working directory for the subprocess.
Definition: Process.h:115
Process(const private_init &)
Definition: Process.h:35
static Option Uid(uv_uid_t uid)
Set the child process' user id.
Definition: Process.h:126
~Process() noexcept override=default
static Option Gid(uv_gid_t gid)
Set the child process' group id.
Definition: Process.h:136
static std::shared_ptr< Process > Spawn(const std::shared_ptr< Loop > &loop, std::string_view file, const Args &... options)
Definition: Process.h:276
static Option StdioInherit(size_t index, int fd)
Inherit a file descriptor from the parent process.
Definition: Process.h:177
void Kill(int signum)
Sends the specified signal to the process.
Definition: Process.h:286
static Option ClearFlags(unsigned int flags)
Clear spawn flags.
Definition: Process.h:156
static Option StdioInherit(size_t index, Pipe &pipe)
Inherit a pipe from the parent process.
Definition: Process.h:189
static std::shared_ptr< Process > SpawnArray(Loop &loop, std::string_view file, std::span< const Option > options)
Starts a process.
basic_string_view< char > string_view
Definition: core.h:520
type
Definition: core.h:575
EIGEN_CONSTEXPR Index size(const T &x)
Definition: Meta.h:479
Definition: Buffer.h:18
flags
Definition: http_parser.h:206
Definition: format.h:1552
int pid
Definition: uv.h:1062
Structure for Spawn() option temporaries.
Definition: Process.h:43
Option(const char *arg)
Definition: Process.h:61
Option()
Definition: Process.h:59
int fd
Definition: Process.h:91
const char * str
Definition: Process.h:84
Option(const std::string &arg)
Definition: Process.h:65
Pipe * pipe
Definition: Process.h:92
uv_gid_t gid
Definition: Process.h:86
uv_uid_t uid
Definition: Process.h:85
size_t index
Definition: Process.h:89
unsigned int flags
Definition: Process.h:87
Option(std::string_view arg)
Definition: Process.h:69
struct wpi::uv::Process::Option::@755::@756 stdio
union wpi::uv::Process::Option::@755 m_data
Option(Type type)
Definition: Process.h:79
std::string m_strData
Definition: Process.h:82
Option(const SmallVectorImpl< char > &arg)
Definition: Process.h:74
Type
Definition: Process.h:44
@ kSetFlags
Definition: Process.h:51
@ kGid
Definition: Process.h:50
@ kNone
Definition: Process.h:45
@ kStdioInheritFd
Definition: Process.h:54
@ kClearFlags
Definition: Process.h:52
@ kEnv
Definition: Process.h:47
@ kUid
Definition: Process.h:49
@ kStdioCreatePipe
Definition: Process.h:56
@ kArg
Definition: Process.h:46
@ kCwd
Definition: Process.h:48
@ kStdioIgnore
Definition: Process.h:53
@ kStdioInheritPipe
Definition: Process.h:55
uid_t uv_uid_t
Definition: unix.h:159
pid_t uv_pid_t
Definition: unix.h:121
gid_t uv_gid_t
Definition: unix.h:158
UV_EXTERN int uv_process_kill(uv_process_t *, int signum)
UV_EXTERN int uv_kill(int pid, int signum)
UV_EXTERN void uv_disable_stdio_inheritance(void)