]>
Commit | Line | Data |
---|---|---|
1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ | |
2 | #pragma once | |
3 | ||
4 | #include "cgroup.h" | |
5 | #include "core-forward.h" | |
6 | #include "exit-status.h" | |
7 | #include "kill.h" | |
8 | #include "pidref.h" | |
9 | #include "unit.h" | |
10 | ||
11 | typedef enum ServiceRestart { | |
12 | SERVICE_RESTART_NO, | |
13 | SERVICE_RESTART_ON_SUCCESS, | |
14 | SERVICE_RESTART_ON_FAILURE, | |
15 | SERVICE_RESTART_ON_ABNORMAL, | |
16 | SERVICE_RESTART_ON_WATCHDOG, | |
17 | SERVICE_RESTART_ON_ABORT, | |
18 | SERVICE_RESTART_ALWAYS, | |
19 | _SERVICE_RESTART_MAX, | |
20 | _SERVICE_RESTART_INVALID = -EINVAL, | |
21 | } ServiceRestart; | |
22 | ||
23 | typedef enum ServiceType { | |
24 | SERVICE_SIMPLE, /* we fork and go on right-away (i.e. modern socket activated daemons) */ | |
25 | SERVICE_FORKING, /* forks by itself (i.e. traditional daemons) */ | |
26 | SERVICE_ONESHOT, /* we fork and wait until the program finishes (i.e. programs like fsck which run and need to finish before we continue) */ | |
27 | SERVICE_DBUS, /* we fork and wait until a specific D-Bus name appears on the bus */ | |
28 | SERVICE_NOTIFY, /* we fork and wait until a daemon sends us a ready message with sd_notify() */ | |
29 | SERVICE_NOTIFY_RELOAD, /* just like SERVICE_NOTIFY, but also implements a reload protocol via SIGHUP */ | |
30 | SERVICE_IDLE, /* much like simple, but delay exec() until all jobs are dispatched. */ | |
31 | SERVICE_EXEC, /* we fork and wait until we execute exec() (this means our own setup is waited for) */ | |
32 | _SERVICE_TYPE_MAX, | |
33 | _SERVICE_TYPE_INVALID = -EINVAL, | |
34 | } ServiceType; | |
35 | ||
36 | typedef enum ServiceExitType { | |
37 | SERVICE_EXIT_MAIN, /* we consider the main PID when deciding if the service exited */ | |
38 | SERVICE_EXIT_CGROUP, /* we wait for the last process in the cgroup to exit */ | |
39 | _SERVICE_EXIT_TYPE_MAX, | |
40 | _SERVICE_EXIT_TYPE_INVALID = -EINVAL, | |
41 | } ServiceExitType; | |
42 | ||
43 | typedef enum ServiceExecCommand { | |
44 | SERVICE_EXEC_CONDITION, | |
45 | SERVICE_EXEC_START_PRE, | |
46 | SERVICE_EXEC_START, | |
47 | SERVICE_EXEC_START_POST, | |
48 | SERVICE_EXEC_RELOAD, | |
49 | SERVICE_EXEC_STOP, | |
50 | SERVICE_EXEC_STOP_POST, | |
51 | _SERVICE_EXEC_COMMAND_MAX, | |
52 | _SERVICE_EXEC_COMMAND_INVALID = -EINVAL, | |
53 | } ServiceExecCommand; | |
54 | ||
55 | typedef enum NotifyState { | |
56 | NOTIFY_UNKNOWN, | |
57 | NOTIFY_READY, | |
58 | NOTIFY_RELOADING, | |
59 | NOTIFY_STOPPING, | |
60 | _NOTIFY_STATE_MAX, | |
61 | _NOTIFY_STATE_INVALID = -EINVAL, | |
62 | } NotifyState; | |
63 | ||
64 | /* The values of this enum are referenced in man/systemd.exec.xml and src/shared/bus-unit-util.c. | |
65 | * Update those sources for each change to this enum. */ | |
66 | typedef enum ServiceResult { | |
67 | SERVICE_SUCCESS, | |
68 | SERVICE_FAILURE_RESOURCES, /* a bit of a misnomer, just our catch-all error for errnos we didn't expect */ | |
69 | SERVICE_FAILURE_PROTOCOL, | |
70 | SERVICE_FAILURE_TIMEOUT, | |
71 | SERVICE_FAILURE_EXIT_CODE, | |
72 | SERVICE_FAILURE_SIGNAL, | |
73 | SERVICE_FAILURE_CORE_DUMP, | |
74 | SERVICE_FAILURE_WATCHDOG, | |
75 | SERVICE_FAILURE_START_LIMIT_HIT, | |
76 | SERVICE_FAILURE_OOM_KILL, /* OOM Kill by the Kernel or systemd-oomd */ | |
77 | SERVICE_SKIP_CONDITION, | |
78 | _SERVICE_RESULT_MAX, | |
79 | _SERVICE_RESULT_INVALID = -EINVAL, | |
80 | } ServiceResult; | |
81 | ||
82 | typedef enum ServiceTimeoutFailureMode { | |
83 | SERVICE_TIMEOUT_TERMINATE, | |
84 | SERVICE_TIMEOUT_ABORT, | |
85 | SERVICE_TIMEOUT_KILL, | |
86 | _SERVICE_TIMEOUT_FAILURE_MODE_MAX, | |
87 | _SERVICE_TIMEOUT_FAILURE_MODE_INVALID = -EINVAL, | |
88 | } ServiceTimeoutFailureMode; | |
89 | ||
90 | typedef enum ServiceRestartMode { | |
91 | SERVICE_RESTART_MODE_NORMAL, | |
92 | SERVICE_RESTART_MODE_DIRECT, | |
93 | SERVICE_RESTART_MODE_DEBUG, | |
94 | _SERVICE_RESTART_MODE_MAX, | |
95 | _SERVICE_RESTART_MODE_INVALID = -EINVAL, | |
96 | } ServiceRestartMode; | |
97 | ||
98 | typedef struct ServiceFDStore { | |
99 | Service *service; | |
100 | ||
101 | int fd; | |
102 | char *fdname; | |
103 | sd_event_source *event_source; | |
104 | bool do_poll; | |
105 | ||
106 | LIST_FIELDS(struct ServiceFDStore, fd_store); | |
107 | } ServiceFDStore; | |
108 | ||
109 | typedef struct ServiceExtraFD { | |
110 | int fd; | |
111 | char *fdname; | |
112 | } ServiceExtraFD; | |
113 | ||
114 | typedef struct Service { | |
115 | Unit meta; | |
116 | ||
117 | ServiceType type; | |
118 | ServiceExitType exit_type; | |
119 | ServiceRestart restart; | |
120 | ServiceRestartMode restart_mode; | |
121 | ExitStatusSet restart_prevent_status; | |
122 | ExitStatusSet restart_force_status; | |
123 | ExitStatusSet success_status; | |
124 | ||
125 | /* If set we'll read the main daemon PID from this file */ | |
126 | char *pid_file; | |
127 | ||
128 | unsigned n_restarts; | |
129 | unsigned restart_steps; | |
130 | usec_t restart_usec; | |
131 | usec_t restart_max_delay_usec; | |
132 | usec_t timeout_start_usec; | |
133 | usec_t timeout_stop_usec; | |
134 | usec_t timeout_abort_usec; | |
135 | bool timeout_abort_set; | |
136 | usec_t runtime_max_usec; | |
137 | usec_t runtime_rand_extra_usec; | |
138 | ServiceTimeoutFailureMode timeout_start_failure_mode; | |
139 | ServiceTimeoutFailureMode timeout_stop_failure_mode; | |
140 | ||
141 | dual_timestamp watchdog_timestamp; | |
142 | usec_t watchdog_usec; /* the requested watchdog timeout in the unit file */ | |
143 | usec_t watchdog_original_usec; /* the watchdog timeout that was in effect when the unit was started, i.e. the timeout the forked off processes currently see */ | |
144 | usec_t watchdog_override_usec; /* the watchdog timeout requested by the service itself through sd_notify() */ | |
145 | bool watchdog_override_enable; | |
146 | sd_event_source *watchdog_event_source; | |
147 | ||
148 | ExecContext exec_context; | |
149 | KillContext kill_context; | |
150 | CGroupContext cgroup_context; | |
151 | ||
152 | ServiceState state, deserialized_state; | |
153 | ||
154 | /* The exit status of the real main process */ | |
155 | ExecStatus main_exec_status; | |
156 | ||
157 | ExecCommand *exec_command[_SERVICE_EXEC_COMMAND_MAX]; | |
158 | ||
159 | /* The currently executed main process, which may be NULL if the main process got started via | |
160 | * forking mode and not by us */ | |
161 | ExecCommand *main_command; | |
162 | ||
163 | /* The currently executed control process */ | |
164 | ExecCommand *control_command; | |
165 | ||
166 | /* The ID of the control command currently being executed */ | |
167 | ServiceExecCommand control_command_id; | |
168 | ||
169 | /* Runtime data of the execution context */ | |
170 | ExecRuntime *exec_runtime; | |
171 | ||
172 | CGroupRuntime *cgroup_runtime; | |
173 | ||
174 | PidRef main_pid, control_pid; | |
175 | ||
176 | /* if we are a socket activated service instance, store information of the connection/peer/socket */ | |
177 | int socket_fd; | |
178 | SocketPeer *socket_peer; | |
179 | UnitRef accept_socket; | |
180 | bool socket_fd_selinux_context_net; | |
181 | ||
182 | bool permissions_start_only; | |
183 | bool root_directory_start_only; | |
184 | bool remain_after_exit; | |
185 | bool guess_main_pid; | |
186 | ||
187 | /* If we shut down, remember why */ | |
188 | ServiceResult result; | |
189 | ServiceResult reload_result; | |
190 | ServiceResult live_mount_result; | |
191 | ServiceResult clean_result; | |
192 | ||
193 | bool main_pid_known:1; | |
194 | bool main_pid_alien:1; | |
195 | bool bus_name_good:1; | |
196 | bool forbid_restart:1; | |
197 | bool start_timeout_defined:1; | |
198 | bool exec_fd_hot:1; | |
199 | ||
200 | char *bus_name; | |
201 | ||
202 | char *status_text; | |
203 | char *status_bus_error; | |
204 | char *status_varlink_error; | |
205 | int status_errno; | |
206 | ||
207 | sd_event_source *timer_event_source; | |
208 | PathSpec *pid_file_pathspec; | |
209 | ||
210 | NotifyAccess notify_access; | |
211 | NotifyAccess notify_access_override; | |
212 | NotifyState notify_state; | |
213 | ||
214 | sd_bus_slot *bus_name_pid_lookup_slot; | |
215 | ||
216 | sd_event_source *exec_fd_event_source; | |
217 | ||
218 | LIST_HEAD(ServiceFDStore, fd_store); | |
219 | size_t n_fd_store; | |
220 | unsigned n_fd_store_max; | |
221 | ExecPreserveMode fd_store_preserve_mode; | |
222 | ||
223 | int stdin_fd; | |
224 | int stdout_fd; | |
225 | int stderr_fd; | |
226 | ||
227 | /* If service spawned from transient unit, extra file descriptors can be passed via dbus API */ | |
228 | ServiceExtraFD *extra_fds; | |
229 | size_t n_extra_fds; | |
230 | ||
231 | LIST_HEAD(OpenFile, open_files); | |
232 | ||
233 | int reload_signal; | |
234 | usec_t reload_begin_usec; | |
235 | ||
236 | OOMPolicy oom_policy; | |
237 | ||
238 | char *usb_function_descriptors; | |
239 | char *usb_function_strings; | |
240 | ||
241 | /* The D-Bus request, we will reply once the operation is finished, so that callers can block */ | |
242 | sd_bus_message *mount_request; | |
243 | } Service; | |
244 | ||
245 | static inline usec_t service_timeout_abort_usec(Service *s) { | |
246 | assert(s); | |
247 | return s->timeout_abort_set ? s->timeout_abort_usec : s->timeout_stop_usec; | |
248 | } | |
249 | ||
250 | static inline NotifyAccess service_get_notify_access(Service *s) { | |
251 | assert(s); | |
252 | return s->notify_access_override < 0 ? s->notify_access : s->notify_access_override; | |
253 | } | |
254 | ||
255 | static inline usec_t service_get_watchdog_usec(Service *s) { | |
256 | assert(s); | |
257 | return s->watchdog_override_enable ? s->watchdog_override_usec : s->watchdog_original_usec; | |
258 | } | |
259 | ||
260 | extern const UnitVTable service_vtable; | |
261 | ||
262 | int service_set_socket_fd(Service *s, int fd, struct Socket *socket, struct SocketPeer *peer, bool selinux_context_net); | |
263 | void service_release_socket_fd(Service *s); | |
264 | ||
265 | usec_t service_restart_usec_next(Service *s); | |
266 | ||
267 | int service_determine_exec_selinux_label(Service *s, char **ret); | |
268 | ||
269 | const char* service_restart_to_string(ServiceRestart i) _const_; | |
270 | ServiceRestart service_restart_from_string(const char *s) _pure_; | |
271 | ||
272 | const char* service_restart_mode_to_string(ServiceRestartMode i) _const_; | |
273 | ServiceRestartMode service_restart_mode_from_string(const char *s) _pure_; | |
274 | ||
275 | const char* service_type_to_string(ServiceType i) _const_; | |
276 | ServiceType service_type_from_string(const char *s) _pure_; | |
277 | ||
278 | const char* service_exit_type_to_string(ServiceExitType i) _const_; | |
279 | ServiceExitType service_exit_type_from_string(const char *s) _pure_; | |
280 | ||
281 | const char* service_exec_command_to_string(ServiceExecCommand i) _const_; | |
282 | ServiceExecCommand service_exec_command_from_string(const char *s) _pure_; | |
283 | ||
284 | const char* service_exec_ex_command_to_string(ServiceExecCommand i) _const_; | |
285 | ServiceExecCommand service_exec_ex_command_from_string(const char *s) _pure_; | |
286 | ||
287 | const char* notify_state_to_string(NotifyState i) _const_; | |
288 | NotifyState notify_state_from_string(const char *s) _pure_; | |
289 | ||
290 | const char* service_result_to_string(ServiceResult i) _const_; | |
291 | ServiceResult service_result_from_string(const char *s) _pure_; | |
292 | ||
293 | const char* service_timeout_failure_mode_to_string(ServiceTimeoutFailureMode i) _const_; | |
294 | ServiceTimeoutFailureMode service_timeout_failure_mode_from_string(const char *s) _pure_; | |
295 | ||
296 | DEFINE_CAST(SERVICE, Service); | |
297 | ||
298 | #define STATUS_TEXT_MAX (16U*1024U) | |
299 | ||
300 | /* Only exported for unit tests */ | |
301 | int service_deserialize_exec_command(Unit *u, const char *key, const char *value); |