master
h 76 lines 4.01 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #ifndef SPAWN_SERVER_H
4 #define SPAWN_SERVER_H
5
6 #include "../common.h"
7
8 #define SPAWN_SERVER_TRANSFER_FDS 4
9
10 typedef enum __attribute__((packed)) {
11 SPAWN_INSTANCE_TYPE_EXEC = 0,
12 SPAWN_INSTANCE_TYPE_CALLBACK = 1
13 } SPAWN_INSTANCE_TYPE;
14
15 typedef enum __attribute__((packed)) {
16 SPAWN_SERVER_OPTION_EXEC = (1 << 0),
17 SPAWN_SERVER_OPTION_CALLBACK = (1 << 1),
18 } SPAWN_SERVER_OPTIONS;
19
20 // this is only used publicly for SPAWN_INSTANCE_TYPE_CALLBACK
21 // which is not available in Windows
22 typedef struct spawn_request {
23 const char *cmdline; // the cmd line of the command we should run
24 size_t request_id; // the incremental request id
25 pid_t pid; // the pid of the child
26 int sock; // the socket for this request
27 int fds[SPAWN_SERVER_TRANSFER_FDS]; // 0 = stdin, 1 = stdout, 2 = stderr, 3 = custom
28 const char **envp; // the environment of the parent process
29 const char **argv; // the command line and its parameters
30 const void *data; // the data structure for the callback
31 size_t data_size; // the data structure size
32 SPAWN_INSTANCE_TYPE type; // the type of the request
33
34 struct spawn_request *prev, *next; // linking of active requests at the spawn server
35 } SPAWN_REQUEST;
36
37 typedef int (*spawn_request_callback_t)(SPAWN_REQUEST *request);
38
39 typedef struct spawn_instance SPAWN_INSTANCE;
40 typedef struct spawn_server SPAWN_SERVER;
41
42 SPAWN_SERVER* spawn_server_create(SPAWN_SERVER_OPTIONS options, const char *name, spawn_request_callback_t child_callback, int argc, const char **argv);
43 void spawn_server_destroy(SPAWN_SERVER *server);
44 pid_t spawn_server_pid(SPAWN_SERVER *server);
45
46 SPAWN_INSTANCE* spawn_server_exec(SPAWN_SERVER *server, int stderr_fd, int custom_fd, const char **argv, const void *data, size_t data_size, SPAWN_INSTANCE_TYPE type);
47 int spawn_server_exec_kill(SPAWN_SERVER *server, SPAWN_INSTANCE *si, int timeout_ms);
48 int spawn_server_exec_wait(SPAWN_SERVER *server, SPAWN_INSTANCE *si);
49
50 typedef enum __attribute__((packed)) {
51 SPAWN_TIMEDWAIT_EXITED = 0, // the child exited; *status holds its status and si has been freed
52 SPAWN_TIMEDWAIT_RUNNING = 1, // the timeout expired; the child is still running and si remains valid
53 SPAWN_TIMEDWAIT_ERROR = 2, // the wait could not be completed (broken status channel / unusable
54 // handle); the child's state is unknown, si remains valid, and the
55 // caller must reclaim it (e.g. via spawn_server_exec_kill())
56 } SPAWN_TIMEDWAIT_RESULT;
57
58 // Wait for the child for up to timeout_ms. A non-positive timeout_ms performs a single, minimal
59 // bounded poll (the nofork backend uses a ~1ms slice because its wait primitive treats 0 as
60 // "wait forever"; the others poll once); the wait is always bounded, never infinite.
61 // On SPAWN_TIMEDWAIT_EXITED the instance has been freed, exactly like spawn_server_exec_wait().
62 // On SPAWN_TIMEDWAIT_RUNNING or SPAWN_TIMEDWAIT_ERROR the caller keeps ownership and must eventually
63 // call spawn_server_exec_timedwait(), spawn_server_exec_wait() or spawn_server_exec_kill().
64 // ERROR is distinct from RUNNING on purpose: the wait could not progress (it is not merely "not yet"),
65 // so callers must NOT loop on it (that would spin forever when timeout_ms == 0) - they must reclaim
66 // the instance, typically by killing it.
67 // status is optional (may be NULL): on EXITED the wait/cleanup still happens, the status is just not stored.
68 SPAWN_TIMEDWAIT_RESULT spawn_server_exec_timedwait(SPAWN_SERVER *server, SPAWN_INSTANCE *si, int timeout_ms, int *status);
69
70 int spawn_server_instance_read_fd(SPAWN_INSTANCE *si);
71 int spawn_server_instance_write_fd(SPAWN_INSTANCE *si);
72 pid_t spawn_server_instance_pid(SPAWN_INSTANCE *si);
73 void spawn_server_instance_read_fd_unset(SPAWN_INSTANCE *si);
74 void spawn_server_instance_write_fd_unset(SPAWN_INSTANCE *si);
75
76 #endif //SPAWN_SERVER_H