BRL-CAD
Loading...
Searching...
No Matches
process.h
Go to the documentation of this file.
1/* P R O C E S S . H
2 * BRL-CAD
3 *
4 * Copyright (c) 2004-2026 United States Government as represented by
5 * the U.S. Army Research Laboratory.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * version 2.1 as published by the Free Software Foundation.
10 *
11 * This library is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this file; see the file named COPYING for more
18 * information.
19 */
20
21#ifndef BU_PROCESS_H
22#define BU_PROCESS_H
23
24#include "common.h"
25
26#include <stdio.h> /* FILE */
27#include "bu/defines.h"
28
30
31/** @addtogroup bu_process
32 *
33 * @brief
34 * Routines for process and sub-process management.
35 */
36/** @{ */
37/** @file bu/process.h */
38
39/* Wrappers for using subprocess execution */
40struct bu_process;
41struct bu_vls;
42
48
49typedef enum {
50 BU_PROCESS_DEFAULT = 0x0, // default process options: equiv to (bu_process_opts)0
51 BU_PROCESS_OUT_EQ_ERR = 0x1, // stdout reads from stderr instead
52 BU_PROCESS_HIDE_WINDOW = 0x2, // (Windows only)hide creation window if process would normally spawn one
54
55#ifndef ERROR_PROCESS_ABORTED
56// have a consistent 'aborted' return code on cross-platforms
57#define ERROR_PROCESS_ABORTED 1067L
58#endif
59
60/**
61 * Callback type used by bu_process_func().
62 *
63 * The callback runs in a subprocess. On POSIX platforms this is
64 * implemented using fork(), so the callback should restrict itself to
65 * fork-safe operations.
66 *
67 * @param[in] data - opaque pointer supplied to bu_process_func()
68 *
69 * @return
70 * integer exit status for the subprocess
71 */
72typedef int (*bu_process_func_t)(void *data);
73
74/**
75 * Status and optional capture buffers for bu_process_func().
76 *
77 * If out and/or err are non-NULL, they must point to initialized
78 * bu_vls containers. bu_process_func() truncates any supplied capture
79 * buffers before appending child process output.
80 */
89
90/**
91 * @brief Wrapper for creating a sub-process. Allocates bu_process and starts process
92 *
93 * @param[out] pinfo - newly allocated process handle, or NULL if setup fails
94 * @param[in] argv - array of command line arguments to executed. Last element MUST be NULL
95 * @param[in] process_creation_opts - bit field for bu_process_opts
96 *
97 * @note Process creation does not guarantee the child started successfully.
98 * Use bu_process_wait_n() to check its exit status.
99 */
100BU_EXPORT extern void bu_process_create(struct bu_process **pinfo, const char **argv, int process_creation_opts);
101
102/**
103 * @brief Run a callback in a subprocess and wait for it to complete.
104 *
105 * The callback runs in an isolated child process. On POSIX
106 * platforms this is implemented using fork(), so the callback should
107 * limit itself to fork-safe operations and communicate results back to
108 * the parent via its return code and any captured output.
109 *
110 * If info is non-NULL, the status fields are populated on return. If
111 * info->out and/or info->err are non-NULL, those initialized bu_vls
112 * buffers are truncated and filled with captured child output. When
113 * BU_PROCESS_OUT_EQ_ERR is supplied, stderr is merged into the stdout
114 * capture buffer; if no stdout buffer is supplied, the merged stream is
115 * captured in info->err when available.
116 *
117 * @param[in,out] info - status record and optional capture buffers. May be NULL
118 * @param[in] func - callback to run in the subprocess
119 * @param[in] data - opaque pointer supplied to func
120 * @param[in] timeout_ms - maximum wait time in milliseconds before forcibly
121 * stopping the subprocess. A value of 0 waits indefinitely
122 * @param[in] flags - subprocess behavior flags. BU_PROCESS_OUT_EQ_ERR is
123 * currently supported; on non-POSIX platforms this API is not yet supported
124 *
125 * @return
126 * callback return code if the subprocess exits normally;
127 * ERROR_PROCESS_ABORTED if it is terminated by a signal or times out;
128 * -1 on setup failure or unsupported platforms
129 */
130BU_EXPORT extern int bu_process_func(struct bu_process_func_info *info, bu_process_func_t func, void *data, int timeout_ms, int flags);
131
132
133/**
134 * @brief wait for a sub-process to complete, release all process
135 * allocations, and release the process itself.
136 *
137 * @param[in,out] pinfo - address of the process handle; set to NULL on return
138 * @param[in] wtime - maximum wait time (in ms) before forcibly stopping the
139 * process. A value of 0 waits indefinitely
140 *
141 * @return
142 * 0 on success; ERROR_PROCESS_ABORTED for aborted process; Otherwise, platform specific exit status
143 */
144BU_EXPORT extern int bu_process_wait_n(struct bu_process **pinfo, int wtime);
145
146
147/**
148 * @brief determine whether process is still running
149 *
150 * @param[in] pinfo - bu_process structure of interest
151 *
152 * @return
153 * 1 if alive, else 0
154 */
155BU_EXPORT extern int bu_process_alive(struct bu_process *pinfo);
156
157
158/**
159 * @brief Poll a subprocess without blocking or releasing its resources.
160 *
161 * Unlike bu_process_alive(), this routine also reports and preserves the
162 * subprocess exit status for a later bu_process_wait_n() call. Completion
163 * does not imply that all subprocess output has been read; callers may continue
164 * reading the process channels before releasing the process with
165 * bu_process_wait_n().
166 *
167 * @param[in] pinfo - bu_process structure of interest
168 * @param[out] exit_status - subprocess exit status when complete; may be NULL
169 *
170 * @return
171 * 1 if the subprocess has completed; 0 if it is still running; -1 on error
172 */
173BU_EXPORT extern int bu_process_poll(struct bu_process *pinfo, int *exit_status);
174
175
176/**
177 * @brief Forcefully terminate a subprocess and its descendants.
178 *
179 * The subprocess remains available to bu_process_poll() and
180 * bu_process_wait_n() so callers can drain output and reap resources.
181 *
182 * @param[in] pinfo - bu_process structure of interest
183 *
184 * @return
185 * non-zero if the process was already complete or termination was requested
186 * successfully; zero on error
187 */
188BU_EXPORT extern int bu_process_terminate(struct bu_process *pinfo);
189
190
191/**
192 * @brief Check a process descriptor for readable data without blocking.
193 *
194 * This is a readiness hint. A zero result does not distinguish between no
195 * data, EOF, and an invalid descriptor or other error. Use
196 * bu_process_poll() to detect completion, perform any final reads, and then
197 * call bu_process_wait_n() to release the process.
198 *
199 * @param[in] fd - file descriptor of interest
200 *
201 * @return
202 * 1 if a read can be attempted without blocking; otherwise 0
203 */
205
206
207/**
208 * @brief Read from a process's specified output channel
209 *
210 * @param[in] pinfo - bu_process structure of interest
211 * @param[in] d - channel (BU_PROCESS_STDOUT, BU_PROCESS_STDERR)
212 * @param[in] n - max number of bytes to be read
213 * @param[out] buff - data read from channel
214 *
215 * @return
216 * returns the number of bytes read into buff; 0 if read is at EOF; -1 on error
217 *
218 * @note the returned number of bytes read may be less than 'n'
219 * in a successful read.
220 */
221BU_EXPORT extern int bu_process_read_n(struct bu_process *pinfo, bu_process_io_t d, int n, char *buff);
222
223
224/**
225 * @brief Open and return a FILE pointer associated with the specified channel.
226 *
227 * Input will be opened write, output and error will be opened
228 * read.
229 *
230 * Caller should not close these FILE pointers directly. Call
231 * bu_process_file_close() instead.
232 *
233 * @param[in] pinfo - bu_process structure of interest
234 * @param[in] d - channel (BU_PROCESS_STDIN, BU_PROCESS_STDOUT, BU_PROCESS_STDERR)
235 *
236 * @return
237 * FILE pointer for specified channel
238 */
239BU_EXPORT extern FILE *bu_process_file_open(struct bu_process *pinfo, bu_process_io_t d);
240
241
242/**
243 * @brief Close any FILE pointers internally opened via bu_process_file_open().
244 *
245 * @param[in] pinfo - bu_process structure of interest
246 * @param[in] d - channel (BU_PROCESS_STDIN, BU_PROCESS_STDOUT, BU_PROCESS_STDERR)
247 */
248BU_EXPORT extern void bu_process_file_close(struct bu_process *pinfo, bu_process_io_t d);
249
250
251/**
252 * @brief Retrieve the file descriptor to the I/O channel associated with the process.
253 *
254 * @param[in] pinfo - bu_process structure of interest
255 * @param[in] d - channel (BU_PROCESS_STDIN, BU_PROCESS_STDOUT, BU_PROCESS_STDERR)
256 *
257 * @return
258 * file descriptor
259 *
260 * @note For Windows cases where HANDLE is needed, use _get_osfhandle
261 */
263
264
265/**
266 * @brief Return the pid of the subprocess.
267 *
268 * @param[in] pinfo - bu_process structure of interest
269 *
270 * @return
271 * process ID
272 */
273BU_EXPORT int bu_process_pid(struct bu_process *pinfo);
274
275
276/**
277 * Reports one or both of the command string and the argv array
278 * used to execute the process.
279 *
280 * The bu_process container owns all strings for both cmd and argv -
281 * for the caller they are read-only.
282 *
283 * If either cmd or argv are NULL they will be skipped - if the
284 * caller only wants one of these outputs the other argument can
285 * be set to NULL.
286 *
287 * @param[in] pinfo - the bu_process structure of interest
288 * @param[out] cmd - pointer to the cmd string used to launch pinfo
289 * @param[out] argv - pointer to the argv array used to launch pinfo
290 *
291 * @return
292 * the corresponding argc count for pinfo's argv array.
293 */
294BU_EXPORT int bu_process_args_n(struct bu_process *pinfo, const char **cmd, const char * const **argv);
295
296
297/**
298 * @brief Return the process ID of the calling process
299 *
300 * @return
301 * process ID
302 */
303BU_EXPORT extern int bu_pid(void);
304
305
306/**
307 * @brief determine whether process is still running using its ID
308 *
309 * @param[in] pid - process ID of interest
310 *
311 * @return
312 * 1 if alive, else 0
313 */
314BU_EXPORT extern int bu_pid_alive(int pid);
315
316
317/**
318 * @brief terminate a given process and any children.
319 *
320 * @param[in] pid - process ID of interest
321 *
322 * @return
323 * returns truthfully whether the process could be killed
324 */
326
327
328/**
329 * @brief detect whether or not a program is being run in interactive mode
330 *
331 * @return
332 * 1 if interactive, else 0
333 */
334BU_EXPORT extern int bu_interactive(void);
335
336
337/** @name Deprecated process APIs
338 * @{ */
339
340/** @deprecated Use bu_process_create(). */
341DEPRECATED BU_EXPORT extern void bu_process_exec(struct bu_process **info, const char *cmd, int argc, const char **argv, int out_eql_err, int hide_window);
342
343/** @deprecated Use bu_process_wait_n(). */
344DEPRECATED BU_EXPORT extern int bu_process_wait(int *aborted, struct bu_process *pinfo, int wtime);
345
346/** @deprecated Use bu_process_read_n(). */
347DEPRECATED BU_EXPORT extern int bu_process_read(char *buff, int *count, struct bu_process *pinfo, bu_process_io_t d, int n);
348
349/** @deprecated Use bu_process_file_open(). */
350DEPRECATED BU_EXPORT extern FILE *bu_process_open(struct bu_process *pinfo, bu_process_io_t d);
351
352/** @deprecated Use bu_process_file_close(). */
353DEPRECATED BU_EXPORT extern void bu_process_close(struct bu_process *pinfo, bu_process_io_t d);
354
355/** @deprecated Use bu_process_args_n(). */
356DEPRECATED BU_EXPORT int bu_process_args(const char **cmd, const char * const **argv, struct bu_process *pinfo);
357
358/** @deprecated Use bu_pid(). */
360
361/** @deprecated Use bu_pid_terminate(). */
363
364/** @} */
365
366/** @} */
367
369
370#endif /* BU_PROCESS_H */
371
372/*
373 * Local Variables:
374 * mode: C
375 * tab-width: 8
376 * indent-tabs-mode: t
377 * c-file-style: "stroustrup"
378 * End:
379 * ex: shiftwidth=4 tabstop=8
380 */
Definition dvec.h:74
Header file for the BRL-CAD common definitions.
int bu_process_fileno(struct bu_process *pinfo, bu_process_io_t d)
Retrieve the file descriptor to the I/O channel associated with the process.
int bu_process_pending(int fd)
Check a process descriptor for readable data without blocking.
int bu_interactive(void)
detect whether or not a program is being run in interactive mode
int bu_process_func(struct bu_process_func_info *info, bu_process_func_t func, void *data, int timeout_ms, int flags)
Run a callback in a subprocess and wait for it to complete.
void bu_process_create(struct bu_process **pinfo, const char **argv, int process_creation_opts)
Wrapper for creating a sub-process. Allocates bu_process and starts process.
int bu_process_terminate(struct bu_process *pinfo)
Forcefully terminate a subprocess and its descendants.
DEPRECATED int bu_terminate(int process)
DEPRECATED int bu_process_args(const char **cmd, const char *const **argv, struct bu_process *pinfo)
FILE * bu_process_file_open(struct bu_process *pinfo, bu_process_io_t d)
Open and return a FILE pointer associated with the specified channel.
bu_process_opts
Definition process.h:49
int bu_pid_alive(int pid)
determine whether process is still running using its ID
DEPRECATED int bu_process_id(void)
int bu_pid(void)
Return the process ID of the calling process.
void bu_process_file_close(struct bu_process *pinfo, bu_process_io_t d)
Close any FILE pointers internally opened via bu_process_file_open().
bu_process_io_t
Definition process.h:43
int bu_process_read_n(struct bu_process *pinfo, bu_process_io_t d, int n, char *buff)
Read from a process's specified output channel.
DEPRECATED int bu_process_read(char *buff, int *count, struct bu_process *pinfo, bu_process_io_t d, int n)
DEPRECATED FILE * bu_process_open(struct bu_process *pinfo, bu_process_io_t d)
int bu_process_wait_n(struct bu_process **pinfo, int wtime)
wait for a sub-process to complete, release all process allocations, and release the process itself.
int bu_process_alive(struct bu_process *pinfo)
determine whether process is still running
DEPRECATED void bu_process_close(struct bu_process *pinfo, bu_process_io_t d)
DEPRECATED int bu_process_wait(int *aborted, struct bu_process *pinfo, int wtime)
int bu_process_args_n(struct bu_process *pinfo, const char **cmd, const char *const **argv)
DEPRECATED void bu_process_exec(struct bu_process **info, const char *cmd, int argc, const char **argv, int out_eql_err, int hide_window)
int bu_pid_terminate(int pid)
terminate a given process and any children.
int bu_process_pid(struct bu_process *pinfo)
Return the pid of the subprocess.
int bu_process_poll(struct bu_process *pinfo, int *exit_status)
Poll a subprocess without blocking or releasing its resources.
int(* bu_process_func_t)(void *data)
Definition process.h:72
@ BU_PROCESS_OUT_EQ_ERR
Definition process.h:51
@ BU_PROCESS_DEFAULT
Definition process.h:50
@ BU_PROCESS_HIDE_WINDOW
Definition process.h:52
@ BU_PROCESS_STDERR
Definition process.h:46
@ BU_PROCESS_STDIN
Definition process.h:44
@ BU_PROCESS_STDOUT
Definition process.h:45
#define DEPRECATED
Definition common.h:439
struct bu_vls * err
Definition process.h:87
struct bu_vls * out
Definition process.h:86
Definition vls.h:53