File: | build-scan/../src/core/service.c |
Warning: | line 1440, column 24 Potential leak of memory pointed to by 'fds' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | ||||
2 | |||||
3 | #include <errno(*__errno_location ()).h> | ||||
4 | #include <signal.h> | ||||
5 | #include <unistd.h> | ||||
6 | |||||
7 | #include "sd-messages.h" | ||||
8 | |||||
9 | #include "alloc-util.h" | ||||
10 | #include "async.h" | ||||
11 | #include "bus-error.h" | ||||
12 | #include "bus-kernel.h" | ||||
13 | #include "bus-util.h" | ||||
14 | #include "dbus-service.h" | ||||
15 | #include "def.h" | ||||
16 | #include "env-util.h" | ||||
17 | #include "escape.h" | ||||
18 | #include "exit-status.h" | ||||
19 | #include "fd-util.h" | ||||
20 | #include "fileio.h" | ||||
21 | #include "format-util.h" | ||||
22 | #include "fs-util.h" | ||||
23 | #include "load-dropin.h" | ||||
24 | #include "load-fragment.h" | ||||
25 | #include "log.h" | ||||
26 | #include "manager.h" | ||||
27 | #include "parse-util.h" | ||||
28 | #include "path-util.h" | ||||
29 | #include "process-util.h" | ||||
30 | #include "service.h" | ||||
31 | #include "signal-util.h" | ||||
32 | #include "special.h" | ||||
33 | #include "stdio-util.h" | ||||
34 | #include "string-table.h" | ||||
35 | #include "string-util.h" | ||||
36 | #include "strv.h" | ||||
37 | #include "unit-name.h" | ||||
38 | #include "unit.h" | ||||
39 | #include "utf8.h" | ||||
40 | #include "util.h" | ||||
41 | |||||
42 | static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = { | ||||
43 | [SERVICE_DEAD] = UNIT_INACTIVE, | ||||
44 | [SERVICE_CONDITION] = UNIT_ACTIVATING, | ||||
45 | [SERVICE_START_PRE] = UNIT_ACTIVATING, | ||||
46 | [SERVICE_START] = UNIT_ACTIVATING, | ||||
47 | [SERVICE_START_POST] = UNIT_ACTIVATING, | ||||
48 | [SERVICE_RUNNING] = UNIT_ACTIVE, | ||||
49 | [SERVICE_EXITED] = UNIT_ACTIVE, | ||||
50 | [SERVICE_RELOAD] = UNIT_RELOADING, | ||||
51 | [SERVICE_STOP] = UNIT_DEACTIVATING, | ||||
52 | [SERVICE_STOP_SIGABRT] = UNIT_DEACTIVATING, | ||||
53 | [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING, | ||||
54 | [SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING, | ||||
55 | [SERVICE_STOP_POST] = UNIT_DEACTIVATING, | ||||
56 | [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING, | ||||
57 | [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING, | ||||
58 | [SERVICE_FAILED] = UNIT_FAILED, | ||||
59 | [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING | ||||
60 | }; | ||||
61 | |||||
62 | /* For Type=idle we never want to delay any other jobs, hence we | ||||
63 | * consider idle jobs active as soon as we start working on them */ | ||||
64 | static const UnitActiveState state_translation_table_idle[_SERVICE_STATE_MAX] = { | ||||
65 | [SERVICE_DEAD] = UNIT_INACTIVE, | ||||
66 | [SERVICE_CONDITION] = UNIT_ACTIVE, | ||||
67 | [SERVICE_START_PRE] = UNIT_ACTIVE, | ||||
68 | [SERVICE_START] = UNIT_ACTIVE, | ||||
69 | [SERVICE_START_POST] = UNIT_ACTIVE, | ||||
70 | [SERVICE_RUNNING] = UNIT_ACTIVE, | ||||
71 | [SERVICE_EXITED] = UNIT_ACTIVE, | ||||
72 | [SERVICE_RELOAD] = UNIT_RELOADING, | ||||
73 | [SERVICE_STOP] = UNIT_DEACTIVATING, | ||||
74 | [SERVICE_STOP_SIGABRT] = UNIT_DEACTIVATING, | ||||
75 | [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING, | ||||
76 | [SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING, | ||||
77 | [SERVICE_STOP_POST] = UNIT_DEACTIVATING, | ||||
78 | [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING, | ||||
79 | [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING, | ||||
80 | [SERVICE_FAILED] = UNIT_FAILED, | ||||
81 | [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING | ||||
82 | }; | ||||
83 | |||||
84 | static int service_dispatch_inotify_io(sd_event_source *source, int fd, uint32_t events, void *userdata); | ||||
85 | static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata); | ||||
86 | static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata); | ||||
87 | static int service_dispatch_exec_io(sd_event_source *source, int fd, uint32_t events, void *userdata); | ||||
88 | |||||
89 | static void service_enter_signal(Service *s, ServiceState state, ServiceResult f); | ||||
90 | static void service_enter_reload_by_notify(Service *s); | ||||
91 | |||||
92 | static void service_init(Unit *u) { | ||||
93 | Service *s = SERVICE(u); | ||||
94 | |||||
95 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/service.c", 95, __PRETTY_FUNCTION__ ); } while (0); | ||||
96 | assert(u->load_state == UNIT_STUB)do { if ((__builtin_expect(!!(!(u->load_state == UNIT_STUB )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("u->load_state == UNIT_STUB" ), "../src/core/service.c", 96, __PRETTY_FUNCTION__); } while (0); | ||||
97 | |||||
98 | s->timeout_start_usec = u->manager->default_timeout_start_usec; | ||||
99 | s->timeout_stop_usec = u->manager->default_timeout_stop_usec; | ||||
100 | s->restart_usec = u->manager->default_restart_usec; | ||||
101 | s->runtime_max_usec = USEC_INFINITY((usec_t) -1); | ||||
102 | s->type = _SERVICE_TYPE_INVALID; | ||||
103 | s->socket_fd = -1; | ||||
104 | s->stdin_fd = s->stdout_fd = s->stderr_fd = -1; | ||||
105 | s->guess_main_pid = true1; | ||||
106 | |||||
107 | s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; | ||||
108 | |||||
109 | s->exec_context.keyring_mode = MANAGER_IS_SYSTEM(u->manager)((u->manager)->unit_file_scope == UNIT_FILE_SYSTEM) ? | ||||
110 | EXEC_KEYRING_PRIVATE : EXEC_KEYRING_INHERIT; | ||||
111 | } | ||||
112 | |||||
113 | static void service_unwatch_control_pid(Service *s) { | ||||
114 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 114, __PRETTY_FUNCTION__ ); } while (0); | ||||
115 | |||||
116 | if (s->control_pid <= 0) | ||||
117 | return; | ||||
118 | |||||
119 | unit_unwatch_pid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), s->control_pid); | ||||
120 | s->control_pid = 0; | ||||
121 | } | ||||
122 | |||||
123 | static void service_unwatch_main_pid(Service *s) { | ||||
124 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 124, __PRETTY_FUNCTION__ ); } while (0); | ||||
125 | |||||
126 | if (s->main_pid <= 0) | ||||
127 | return; | ||||
128 | |||||
129 | unit_unwatch_pid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), s->main_pid); | ||||
130 | s->main_pid = 0; | ||||
131 | } | ||||
132 | |||||
133 | static void service_unwatch_pid_file(Service *s) { | ||||
134 | if (!s->pid_file_pathspec) | ||||
135 | return; | ||||
136 | |||||
137 | log_unit_debug(UNIT(s), "Stopping watch for PID file %s", s->pid_file_pathspec->path)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 137, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Stopping watch for PID file %s" , s->pid_file_pathspec->path) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((7))), 0, "../src/core/service.c", 137, __func__ , "Stopping watch for PID file %s", s->pid_file_pathspec-> path); }); | ||||
138 | path_spec_unwatch(s->pid_file_pathspec); | ||||
139 | path_spec_done(s->pid_file_pathspec); | ||||
140 | s->pid_file_pathspec = mfree(s->pid_file_pathspec); | ||||
141 | } | ||||
142 | |||||
143 | static int service_set_main_pid(Service *s, pid_t pid) { | ||||
144 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 144, __PRETTY_FUNCTION__ ); } while (0); | ||||
145 | |||||
146 | if (pid <= 1) | ||||
147 | return -EINVAL22; | ||||
148 | |||||
149 | if (pid == getpid_cached()) | ||||
150 | return -EINVAL22; | ||||
151 | |||||
152 | if (s->main_pid == pid && s->main_pid_known) | ||||
153 | return 0; | ||||
154 | |||||
155 | if (s->main_pid != pid) { | ||||
156 | service_unwatch_main_pid(s); | ||||
157 | exec_status_start(&s->main_exec_status, pid); | ||||
158 | } | ||||
159 | |||||
160 | s->main_pid = pid; | ||||
161 | s->main_pid_known = true1; | ||||
162 | s->main_pid_alien = pid_is_my_child(pid) == 0; | ||||
163 | |||||
164 | if (s->main_pid_alien) | ||||
165 | log_unit_warning(UNIT(s), "Supervising process "PID_FMT" which is not our child. We'll most likely not notice when it exits.", pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 165, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Supervising process ""%" "i"" which is not our child. We'll most likely not notice when it exits." , pid) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/service.c", 165, __func__, "Supervising process " "%" "i"" which is not our child. We'll most likely not notice when it exits." , pid); }); | ||||
166 | |||||
167 | return 0; | ||||
168 | } | ||||
169 | |||||
170 | void service_close_socket_fd(Service *s) { | ||||
171 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 171, __PRETTY_FUNCTION__ ); } while (0); | ||||
172 | |||||
173 | /* Undo the effect of service_set_socket_fd(). */ | ||||
174 | |||||
175 | s->socket_fd = asynchronous_close(s->socket_fd); | ||||
176 | |||||
177 | if (UNIT_ISSET(s->accept_socket)(!!(s->accept_socket).target)) { | ||||
178 | socket_connection_unref(SOCKET(UNIT_DEREF(s->accept_socket)((s->accept_socket).target))); | ||||
179 | unit_ref_unset(&s->accept_socket); | ||||
180 | } | ||||
181 | } | ||||
182 | |||||
183 | static void service_stop_watchdog(Service *s) { | ||||
184 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 184, __PRETTY_FUNCTION__ ); } while (0); | ||||
185 | |||||
186 | s->watchdog_event_source = sd_event_source_unref(s->watchdog_event_source); | ||||
187 | s->watchdog_timestamp = DUAL_TIMESTAMP_NULL((struct dual_timestamp) {}); | ||||
188 | } | ||||
189 | |||||
190 | static usec_t service_get_watchdog_usec(Service *s) { | ||||
191 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 191, __PRETTY_FUNCTION__ ); } while (0); | ||||
192 | |||||
193 | if (s->watchdog_override_enable) | ||||
194 | return s->watchdog_override_usec; | ||||
195 | else | ||||
196 | return s->watchdog_usec; | ||||
197 | } | ||||
198 | |||||
199 | static void service_start_watchdog(Service *s) { | ||||
200 | int r; | ||||
201 | usec_t watchdog_usec; | ||||
202 | |||||
203 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 203, __PRETTY_FUNCTION__ ); } while (0); | ||||
204 | |||||
205 | watchdog_usec = service_get_watchdog_usec(s); | ||||
206 | if (IN_SET(watchdog_usec, 0, USEC_INFINITY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){0, ((usec_t) -1)})/sizeof(int)]; switch( watchdog_usec) { case 0: case ((usec_t) -1): _found = 1; break ; default: break; } _found; })) | ||||
207 | return; | ||||
208 | |||||
209 | if (s->watchdog_event_source) { | ||||
210 | r = sd_event_source_set_time(s->watchdog_event_source, usec_add(s->watchdog_timestamp.monotonic, watchdog_usec)); | ||||
211 | if (r < 0) { | ||||
212 | log_unit_warning_errno(UNIT(s), r, "Failed to reset watchdog timer: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 212, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to reset watchdog timer: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 212, __func__, "Failed to reset watchdog timer: %m" ); }); | ||||
213 | return; | ||||
214 | } | ||||
215 | |||||
216 | r = sd_event_source_set_enabled(s->watchdog_event_source, SD_EVENT_ONESHOT); | ||||
217 | } else { | ||||
218 | r = sd_event_add_time( | ||||
219 | UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->event, | ||||
220 | &s->watchdog_event_source, | ||||
221 | CLOCK_MONOTONIC1, | ||||
222 | usec_add(s->watchdog_timestamp.monotonic, watchdog_usec), 0, | ||||
223 | service_dispatch_watchdog, s); | ||||
224 | if (r < 0) { | ||||
225 | log_unit_warning_errno(UNIT(s), r, "Failed to add watchdog timer: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 225, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to add watchdog timer: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 225, __func__, "Failed to add watchdog timer: %m" ); }); | ||||
226 | return; | ||||
227 | } | ||||
228 | |||||
229 | (void) sd_event_source_set_description(s->watchdog_event_source, "service-watchdog"); | ||||
230 | |||||
231 | /* Let's process everything else which might be a sign | ||||
232 | * of living before we consider a service died. */ | ||||
233 | r = sd_event_source_set_priority(s->watchdog_event_source, SD_EVENT_PRIORITY_IDLE); | ||||
234 | } | ||||
235 | |||||
236 | if (r < 0) | ||||
237 | log_unit_warning_errno(UNIT(s), r, "Failed to install watchdog timer: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 237, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to install watchdog timer: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 237, __func__, "Failed to install watchdog timer: %m" ); }); | ||||
238 | } | ||||
239 | |||||
240 | static void service_extend_timeout(Service *s, usec_t extend_timeout_usec) { | ||||
241 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 241, __PRETTY_FUNCTION__ ); } while (0); | ||||
242 | |||||
243 | if (s->timer_event_source) { | ||||
244 | uint64_t current = 0, extended = 0; | ||||
245 | int r; | ||||
246 | |||||
247 | if (IN_SET(extend_timeout_usec, 0, USEC_INFINITY)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){0, ((usec_t) -1)})/sizeof(int)]; switch( extend_timeout_usec) { case 0: case ((usec_t) -1): _found = 1 ; break; default: break; } _found; })) | ||||
248 | return; | ||||
249 | |||||
250 | extended = usec_add(now(CLOCK_MONOTONIC1), extend_timeout_usec); | ||||
251 | |||||
252 | r = sd_event_source_get_time(s->timer_event_source, ¤t); | ||||
253 | if (r < 0) | ||||
254 | log_unit_error_errno(UNIT(s), r, "Failed to retrieve timeout timer: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/service.c", 254, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to retrieve timeout timer: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/service.c", 254, __func__, "Failed to retrieve timeout timer: %m" ); }); | ||||
255 | else if (extended > current) { | ||||
256 | r = sd_event_source_set_time(s->timer_event_source, extended); | ||||
257 | if (r < 0) | ||||
258 | log_unit_warning_errno(UNIT(s), r, "Failed to set timeout timer: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 258, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to set timeout timer: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 258, __func__, "Failed to set timeout timer: %m" ); }); | ||||
259 | } | ||||
260 | |||||
261 | if (s->watchdog_event_source) { | ||||
262 | /* extend watchdog if necessary. We've asked for an extended timeout so we | ||||
263 | * shouldn't expect a watchdog timeout in the interval in between */ | ||||
264 | r = sd_event_source_get_time(s->watchdog_event_source, ¤t); | ||||
265 | if (r < 0) { | ||||
266 | log_unit_error_errno(UNIT(s), r, "Failed to retrieve watchdog timer: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/service.c", 266, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to retrieve watchdog timer: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/service.c", 266, __func__, "Failed to retrieve watchdog timer: %m" ); }); | ||||
267 | return; | ||||
268 | } | ||||
269 | |||||
270 | if (extended > current) { | ||||
271 | r = sd_event_source_set_time(s->watchdog_event_source, extended); | ||||
272 | if (r < 0) | ||||
273 | log_unit_warning_errno(UNIT(s), r, "Failed to set watchdog timer: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 273, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to set watchdog timer: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 273, __func__, "Failed to set watchdog timer: %m" ); }); | ||||
274 | } | ||||
275 | } | ||||
276 | } | ||||
277 | } | ||||
278 | |||||
279 | static void service_reset_watchdog(Service *s) { | ||||
280 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 280, __PRETTY_FUNCTION__ ); } while (0); | ||||
281 | |||||
282 | dual_timestamp_get(&s->watchdog_timestamp); | ||||
283 | service_start_watchdog(s); | ||||
284 | } | ||||
285 | |||||
286 | static void service_reset_watchdog_timeout(Service *s, usec_t watchdog_override_usec) { | ||||
287 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 287, __PRETTY_FUNCTION__ ); } while (0); | ||||
288 | |||||
289 | s->watchdog_override_enable = true1; | ||||
290 | s->watchdog_override_usec = watchdog_override_usec; | ||||
291 | service_reset_watchdog(s); | ||||
292 | |||||
293 | log_unit_debug(UNIT(s), "watchdog_usec="USEC_FMT, s->watchdog_usec)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 293, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "watchdog_usec=""%" "l" "u", s ->watchdog_usec) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 293, __func__ , "watchdog_usec=""%" "l" "u", s->watchdog_usec); }); | ||||
294 | log_unit_debug(UNIT(s), "watchdog_override_usec="USEC_FMT, s->watchdog_override_usec)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 294, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "watchdog_override_usec=""%" "l" "u", s->watchdog_override_usec) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((7))), 0, "../src/core/service.c", 294, __func__ , "watchdog_override_usec=""%" "l" "u", s->watchdog_override_usec ); }); | ||||
295 | } | ||||
296 | |||||
297 | static void service_fd_store_unlink(ServiceFDStore *fs) { | ||||
298 | |||||
299 | if (!fs) | ||||
300 | return; | ||||
301 | |||||
302 | if (fs->service) { | ||||
303 | assert(fs->service->n_fd_store > 0)do { if ((__builtin_expect(!!(!(fs->service->n_fd_store > 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("fs->service->n_fd_store > 0" ), "../src/core/service.c", 303, __PRETTY_FUNCTION__); } while (0); | ||||
304 | LIST_REMOVE(fd_store, fs->service->fd_store, fs)do { typeof(*(fs->service->fd_store)) **_head = &(fs ->service->fd_store), *_item = (fs); do { if ((__builtin_expect (!!(!(_item)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/core/service.c", 304, __PRETTY_FUNCTION__ ); } while (0); if (_item->fd_store_next) _item->fd_store_next ->fd_store_prev = _item->fd_store_prev; if (_item->fd_store_prev ) _item->fd_store_prev->fd_store_next = _item->fd_store_next ; else { do { if ((__builtin_expect(!!(!(*_head == _item)),0) )) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("*_head == _item" ), "../src/core/service.c", 304, __PRETTY_FUNCTION__); } while (0); *_head = _item->fd_store_next; } _item->fd_store_next = _item->fd_store_prev = ((void*)0); } while (0); | ||||
305 | fs->service->n_fd_store--; | ||||
306 | } | ||||
307 | |||||
308 | if (fs->event_source) { | ||||
309 | sd_event_source_set_enabled(fs->event_source, SD_EVENT_OFF); | ||||
310 | sd_event_source_unref(fs->event_source); | ||||
311 | } | ||||
312 | |||||
313 | free(fs->fdname); | ||||
314 | safe_close(fs->fd); | ||||
315 | free(fs); | ||||
316 | } | ||||
317 | |||||
318 | static void service_release_fd_store(Service *s) { | ||||
319 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 319, __PRETTY_FUNCTION__ ); } while (0); | ||||
320 | |||||
321 | if (s->n_keep_fd_store > 0) | ||||
322 | return; | ||||
323 | |||||
324 | log_unit_debug(UNIT(s), "Releasing all stored fds")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 324, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Releasing all stored fds") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 324, __func__, "Releasing all stored fds"); }); | ||||
325 | while (s->fd_store) | ||||
326 | service_fd_store_unlink(s->fd_store); | ||||
327 | |||||
328 | assert(s->n_fd_store == 0)do { if ((__builtin_expect(!!(!(s->n_fd_store == 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s->n_fd_store == 0"), "../src/core/service.c" , 328, __PRETTY_FUNCTION__); } while (0); | ||||
329 | } | ||||
330 | |||||
331 | static void service_release_resources(Unit *u) { | ||||
332 | Service *s = SERVICE(u); | ||||
333 | |||||
334 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 334, __PRETTY_FUNCTION__ ); } while (0); | ||||
335 | |||||
336 | if (!s->fd_store && s->stdin_fd < 0 && s->stdout_fd < 0 && s->stderr_fd < 0) | ||||
337 | return; | ||||
338 | |||||
339 | log_unit_debug(u, "Releasing resources.")({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 339, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Releasing resources.") : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((7))), 0, "../src/core/service.c", 339, __func__ , "Releasing resources."); }); | ||||
340 | |||||
341 | s->stdin_fd = safe_close(s->stdin_fd); | ||||
342 | s->stdout_fd = safe_close(s->stdout_fd); | ||||
343 | s->stderr_fd = safe_close(s->stderr_fd); | ||||
344 | |||||
345 | service_release_fd_store(s); | ||||
346 | } | ||||
347 | |||||
348 | static void service_done(Unit *u) { | ||||
349 | Service *s = SERVICE(u); | ||||
350 | |||||
351 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 351, __PRETTY_FUNCTION__ ); } while (0); | ||||
352 | |||||
353 | s->pid_file = mfree(s->pid_file); | ||||
354 | s->status_text = mfree(s->status_text); | ||||
355 | |||||
356 | s->exec_runtime = exec_runtime_unref(s->exec_runtime, false0); | ||||
357 | exec_command_free_array(s->exec_command, _SERVICE_EXEC_COMMAND_MAX); | ||||
358 | s->control_command = NULL((void*)0); | ||||
359 | s->main_command = NULL((void*)0); | ||||
360 | |||||
361 | dynamic_creds_unref(&s->dynamic_creds); | ||||
362 | |||||
363 | exit_status_set_free(&s->restart_prevent_status); | ||||
364 | exit_status_set_free(&s->restart_force_status); | ||||
365 | exit_status_set_free(&s->success_status); | ||||
366 | |||||
367 | /* This will leak a process, but at least no memory or any of | ||||
368 | * our resources */ | ||||
369 | service_unwatch_main_pid(s); | ||||
370 | service_unwatch_control_pid(s); | ||||
371 | service_unwatch_pid_file(s); | ||||
372 | |||||
373 | if (s->bus_name) { | ||||
374 | unit_unwatch_bus_name(u, s->bus_name); | ||||
375 | s->bus_name = mfree(s->bus_name); | ||||
376 | } | ||||
377 | |||||
378 | s->bus_name_owner = mfree(s->bus_name_owner); | ||||
379 | |||||
380 | s->usb_function_descriptors = mfree(s->usb_function_descriptors); | ||||
381 | s->usb_function_strings = mfree(s->usb_function_strings); | ||||
382 | |||||
383 | service_close_socket_fd(s); | ||||
384 | s->peer = socket_peer_unref(s->peer); | ||||
385 | |||||
386 | unit_ref_unset(&s->accept_socket); | ||||
387 | |||||
388 | service_stop_watchdog(s); | ||||
389 | |||||
390 | s->timer_event_source = sd_event_source_unref(s->timer_event_source); | ||||
391 | s->exec_fd_event_source = sd_event_source_unref(s->exec_fd_event_source); | ||||
392 | |||||
393 | service_release_resources(u); | ||||
394 | } | ||||
395 | |||||
396 | static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *userdata) { | ||||
397 | ServiceFDStore *fs = userdata; | ||||
398 | |||||
399 | assert(e)do { if ((__builtin_expect(!!(!(e)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("e"), "../src/core/service.c", 399, __PRETTY_FUNCTION__ ); } while (0); | ||||
400 | assert(fs)do { if ((__builtin_expect(!!(!(fs)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fs"), "../src/core/service.c", 400, __PRETTY_FUNCTION__ ); } while (0); | ||||
401 | |||||
402 | /* If we get either EPOLLHUP or EPOLLERR, it's time to remove this entry from the fd store */ | ||||
403 | log_unit_debug(UNIT(fs->service),({ const Unit *_u = (({ typeof(fs->service) _u_ = (fs-> service); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal(7, 0, "../src/core/service.c" , 406, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Received %s on stored fd %d (%s), closing.", revents & EPOLLERR ? "EPOLLERR" : "EPOLLHUP", fs->fd, strna(fs-> fdname)) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 406, __func__, "Received %s on stored fd %d (%s), closing." , revents & EPOLLERR ? "EPOLLERR" : "EPOLLHUP", fs->fd , strna(fs->fdname)); }) | ||||
404 | "Received %s on stored fd %d (%s), closing.",({ const Unit *_u = (({ typeof(fs->service) _u_ = (fs-> service); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal(7, 0, "../src/core/service.c" , 406, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Received %s on stored fd %d (%s), closing.", revents & EPOLLERR ? "EPOLLERR" : "EPOLLHUP", fs->fd, strna(fs-> fdname)) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 406, __func__, "Received %s on stored fd %d (%s), closing." , revents & EPOLLERR ? "EPOLLERR" : "EPOLLHUP", fs->fd , strna(fs->fdname)); }) | ||||
405 | revents & EPOLLERR ? "EPOLLERR" : "EPOLLHUP",({ const Unit *_u = (({ typeof(fs->service) _u_ = (fs-> service); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal(7, 0, "../src/core/service.c" , 406, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Received %s on stored fd %d (%s), closing.", revents & EPOLLERR ? "EPOLLERR" : "EPOLLHUP", fs->fd, strna(fs-> fdname)) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 406, __func__, "Received %s on stored fd %d (%s), closing." , revents & EPOLLERR ? "EPOLLERR" : "EPOLLHUP", fs->fd , strna(fs->fdname)); }) | ||||
406 | fs->fd, strna(fs->fdname))({ const Unit *_u = (({ typeof(fs->service) _u_ = (fs-> service); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal(7, 0, "../src/core/service.c" , 406, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Received %s on stored fd %d (%s), closing.", revents & EPOLLERR ? "EPOLLERR" : "EPOLLHUP", fs->fd, strna(fs-> fdname)) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 406, __func__, "Received %s on stored fd %d (%s), closing." , revents & EPOLLERR ? "EPOLLERR" : "EPOLLHUP", fs->fd , strna(fs->fdname)); }); | ||||
407 | service_fd_store_unlink(fs); | ||||
408 | return 0; | ||||
409 | } | ||||
410 | |||||
411 | static int service_add_fd_store(Service *s, int fd, const char *name) { | ||||
412 | ServiceFDStore *fs; | ||||
413 | int r; | ||||
414 | |||||
415 | /* fd is always consumed if we return >= 0 */ | ||||
416 | |||||
417 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 417, __PRETTY_FUNCTION__ ); } while (0); | ||||
418 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/core/service.c", 418 , __PRETTY_FUNCTION__); } while (0); | ||||
419 | |||||
420 | if (s->n_fd_store >= s->n_fd_store_max) | ||||
421 | return -EXFULL54; /* Our store is full. | ||||
422 | * Use this errno rather than E[NM]FILE to distinguish from | ||||
423 | * the case where systemd itself hits the file limit. */ | ||||
424 | |||||
425 | LIST_FOREACH(fd_store, fs, s->fd_store)for ((fs) = (s->fd_store); (fs); (fs) = (fs)->fd_store_next ) { | ||||
426 | r = same_fd(fs->fd, fd); | ||||
427 | if (r < 0) | ||||
428 | return r; | ||||
429 | if (r > 0) { | ||||
430 | safe_close(fd); | ||||
431 | return 0; /* fd already included */ | ||||
432 | } | ||||
433 | } | ||||
434 | |||||
435 | fs = new0(ServiceFDStore, 1)((ServiceFDStore*) calloc((1), sizeof(ServiceFDStore))); | ||||
436 | if (!fs) | ||||
437 | return -ENOMEM12; | ||||
438 | |||||
439 | fs->fd = fd; | ||||
440 | fs->service = s; | ||||
441 | fs->fdname = strdup(name ?: "stored"); | ||||
442 | if (!fs->fdname) { | ||||
443 | free(fs); | ||||
444 | return -ENOMEM12; | ||||
445 | } | ||||
446 | |||||
447 | r = sd_event_add_io(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->event, &fs->event_source, fd, 0, on_fd_store_io, fs); | ||||
448 | if (r < 0 && r != -EPERM1) { /* EPERM indicates fds that aren't pollable, which is OK */ | ||||
449 | free(fs->fdname); | ||||
450 | free(fs); | ||||
451 | return r; | ||||
452 | } else if (r >= 0) | ||||
453 | (void) sd_event_source_set_description(fs->event_source, "service-fd-store"); | ||||
454 | |||||
455 | LIST_PREPEND(fd_store, s->fd_store, fs)do { typeof(*(s->fd_store)) **_head = &(s->fd_store ), *_item = (fs); do { if ((__builtin_expect(!!(!(_item)),0)) ) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("_item"), "../src/core/service.c" , 455, __PRETTY_FUNCTION__); } while (0); if ((_item->fd_store_next = *_head)) _item->fd_store_next->fd_store_prev = _item ; _item->fd_store_prev = ((void*)0); *_head = _item; } while (0); | ||||
456 | s->n_fd_store++; | ||||
457 | |||||
458 | return 1; /* fd newly stored */ | ||||
459 | } | ||||
460 | |||||
461 | static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name) { | ||||
462 | int r; | ||||
463 | |||||
464 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 464, __PRETTY_FUNCTION__ ); } while (0); | ||||
465 | |||||
466 | while (fdset_size(fds) > 0) { | ||||
467 | _cleanup_close___attribute__((cleanup(closep))) int fd = -1; | ||||
468 | |||||
469 | fd = fdset_steal_first(fds); | ||||
470 | if (fd < 0) | ||||
471 | break; | ||||
472 | |||||
473 | r = service_add_fd_store(s, fd, name); | ||||
474 | if (r == -EXFULL54) | ||||
475 | return log_unit_warning_errno(UNIT(s), r,({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 477, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Cannot store more fds than FileDescriptorStoreMax=%u, closing remaining." , s->n_fd_store_max) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), r, "../src/core/service.c", 477, __func__ , "Cannot store more fds than FileDescriptorStoreMax=%u, closing remaining." , s->n_fd_store_max); }) | ||||
476 | "Cannot store more fds than FileDescriptorStoreMax=%u, closing remaining.",({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 477, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Cannot store more fds than FileDescriptorStoreMax=%u, closing remaining." , s->n_fd_store_max) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), r, "../src/core/service.c", 477, __func__ , "Cannot store more fds than FileDescriptorStoreMax=%u, closing remaining." , s->n_fd_store_max); }) | ||||
477 | s->n_fd_store_max)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 477, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Cannot store more fds than FileDescriptorStoreMax=%u, closing remaining." , s->n_fd_store_max) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), r, "../src/core/service.c", 477, __func__ , "Cannot store more fds than FileDescriptorStoreMax=%u, closing remaining." , s->n_fd_store_max); }); | ||||
478 | if (r < 0) | ||||
479 | return log_unit_error_errno(UNIT(s), r, "Failed to add fd to store: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/service.c", 479, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to add fd to store: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/service.c", 479, __func__, "Failed to add fd to store: %m" ); }); | ||||
480 | if (r > 0) | ||||
481 | log_unit_debug(UNIT(s), "Added fd %u (%s) to fd store.", fd, strna(name))({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 481, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Added fd %u (%s) to fd store." , fd, strna(name)) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 481, __func__, "Added fd %u (%s) to fd store." , fd, strna(name)); }); | ||||
482 | fd = -1; | ||||
483 | } | ||||
484 | |||||
485 | return 0; | ||||
486 | } | ||||
487 | |||||
488 | static void service_remove_fd_store(Service *s, const char *name) { | ||||
489 | ServiceFDStore *fs, *n; | ||||
490 | |||||
491 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 491, __PRETTY_FUNCTION__ ); } while (0); | ||||
492 | assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("name"), "../src/core/service.c", 492, __PRETTY_FUNCTION__ ); } while (0); | ||||
493 | |||||
494 | LIST_FOREACH_SAFE(fd_store, fs, n, s->fd_store)for ((fs) = (s->fd_store); (fs) && (((n) = (fs)-> fd_store_next), 1); (fs) = (n)) { | ||||
495 | if (!streq(fs->fdname, name)(strcmp((fs->fdname),(name)) == 0)) | ||||
496 | continue; | ||||
497 | |||||
498 | log_unit_debug(UNIT(s), "Got explicit request to remove fd %i (%s), closing.", fs->fd, name)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 498, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got explicit request to remove fd %i (%s), closing." , fs->fd, name) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 498, __func__, "Got explicit request to remove fd %i (%s), closing." , fs->fd, name); }); | ||||
499 | service_fd_store_unlink(fs); | ||||
500 | } | ||||
501 | } | ||||
502 | |||||
503 | static int service_arm_timer(Service *s, usec_t usec) { | ||||
504 | int r; | ||||
505 | |||||
506 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 506, __PRETTY_FUNCTION__ ); } while (0); | ||||
507 | |||||
508 | if (s->timer_event_source) { | ||||
509 | r = sd_event_source_set_time(s->timer_event_source, usec); | ||||
510 | if (r < 0) | ||||
511 | return r; | ||||
512 | |||||
513 | return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT); | ||||
514 | } | ||||
515 | |||||
516 | if (usec == USEC_INFINITY((usec_t) -1)) | ||||
517 | return 0; | ||||
518 | |||||
519 | r = sd_event_add_time( | ||||
520 | UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->event, | ||||
521 | &s->timer_event_source, | ||||
522 | CLOCK_MONOTONIC1, | ||||
523 | usec, 0, | ||||
524 | service_dispatch_timer, s); | ||||
525 | if (r < 0) | ||||
526 | return r; | ||||
527 | |||||
528 | (void) sd_event_source_set_description(s->timer_event_source, "service-timer"); | ||||
529 | |||||
530 | return 0; | ||||
531 | } | ||||
532 | |||||
533 | static int service_verify(Service *s) { | ||||
534 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 534, __PRETTY_FUNCTION__ ); } while (0); | ||||
535 | |||||
536 | if (UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->load_state != UNIT_LOADED) | ||||
537 | return 0; | ||||
538 | |||||
539 | if (!s->exec_command[SERVICE_EXEC_START] && !s->exec_command[SERVICE_EXEC_STOP]) { | ||||
540 | log_unit_error(UNIT(s), "Service lacks both ExecStart= and ExecStop= setting. Refusing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/service.c", 540, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service lacks both ExecStart= and ExecStop= setting. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/service.c", 540, __func__, "Service lacks both ExecStart= and ExecStop= setting. Refusing." ); }); | ||||
541 | return -ENOEXEC8; | ||||
542 | } | ||||
543 | |||||
544 | if (s->type != SERVICE_ONESHOT && !s->exec_command[SERVICE_EXEC_START]) { | ||||
545 | log_unit_error(UNIT(s), "Service has no ExecStart= setting, which is only allowed for Type=oneshot services. Refusing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/service.c", 545, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service has no ExecStart= setting, which is only allowed for Type=oneshot services. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/service.c", 545, __func__, "Service has no ExecStart= setting, which is only allowed for Type=oneshot services. Refusing." ); }); | ||||
546 | return -ENOEXEC8; | ||||
547 | } | ||||
548 | |||||
549 | if (!s->remain_after_exit && !s->exec_command[SERVICE_EXEC_START]) { | ||||
550 | log_unit_error(UNIT(s), "Service has no ExecStart= setting, which is only allowed for RemainAfterExit=yes services. Refusing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/service.c", 550, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service has no ExecStart= setting, which is only allowed for RemainAfterExit=yes services. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/service.c", 550, __func__, "Service has no ExecStart= setting, which is only allowed for RemainAfterExit=yes services. Refusing." ); }); | ||||
551 | return -ENOEXEC8; | ||||
552 | } | ||||
553 | |||||
554 | if (s->type != SERVICE_ONESHOT && s->exec_command[SERVICE_EXEC_START]->command_next) { | ||||
555 | log_unit_error(UNIT(s), "Service has more than one ExecStart= setting, which is only allowed for Type=oneshot services. Refusing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/service.c", 555, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service has more than one ExecStart= setting, which is only allowed for Type=oneshot services. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/service.c", 555, __func__, "Service has more than one ExecStart= setting, which is only allowed for Type=oneshot services. Refusing." ); }); | ||||
556 | return -ENOEXEC8; | ||||
557 | } | ||||
558 | |||||
559 | if (s->type == SERVICE_ONESHOT && s->restart != SERVICE_RESTART_NO) { | ||||
560 | log_unit_error(UNIT(s), "Service has Restart= setting other than no, which isn't allowed for Type=oneshot services. Refusing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/service.c", 560, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service has Restart= setting other than no, which isn't allowed for Type=oneshot services. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/service.c", 560, __func__, "Service has Restart= setting other than no, which isn't allowed for Type=oneshot services. Refusing." ); }); | ||||
561 | return -ENOEXEC8; | ||||
562 | } | ||||
563 | |||||
564 | if (s->type == SERVICE_ONESHOT && !exit_status_set_is_empty(&s->restart_force_status)) { | ||||
565 | log_unit_error(UNIT(s), "Service has RestartForceStatus= set, which isn't allowed for Type=oneshot services. Refusing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/service.c", 565, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service has RestartForceStatus= set, which isn't allowed for Type=oneshot services. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/service.c", 565, __func__, "Service has RestartForceStatus= set, which isn't allowed for Type=oneshot services. Refusing." ); }); | ||||
566 | return -ENOEXEC8; | ||||
567 | } | ||||
568 | |||||
569 | if (s->type == SERVICE_DBUS && !s->bus_name) { | ||||
570 | log_unit_error(UNIT(s), "Service is of type D-Bus but no D-Bus service name has been specified. Refusing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/service.c", 570, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service is of type D-Bus but no D-Bus service name has been specified. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/service.c", 570, __func__, "Service is of type D-Bus but no D-Bus service name has been specified. Refusing." ); }); | ||||
571 | return -ENOEXEC8; | ||||
572 | } | ||||
573 | |||||
574 | if (s->bus_name && s->type != SERVICE_DBUS) | ||||
575 | log_unit_warning(UNIT(s), "Service has a D-Bus service name specified, but is not of type dbus. Ignoring.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 575, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service has a D-Bus service name specified, but is not of type dbus. Ignoring." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 575, __func__, "Service has a D-Bus service name specified, but is not of type dbus. Ignoring." ); }); | ||||
576 | |||||
577 | if (s->exec_context.pam_name && !IN_SET(s->kill_context.kill_mode, KILL_CONTROL_GROUP, KILL_MIXED)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){KILL_CONTROL_GROUP, KILL_MIXED})/sizeof( int)]; switch(s->kill_context.kill_mode) { case KILL_CONTROL_GROUP : case KILL_MIXED: _found = 1; break; default: break; } _found ; })) { | ||||
578 | log_unit_error(UNIT(s), "Service has PAM enabled. Kill mode must be set to 'control-group' or 'mixed'. Refusing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/service.c", 578, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service has PAM enabled. Kill mode must be set to 'control-group' or 'mixed'. Refusing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/service.c", 578, __func__, "Service has PAM enabled. Kill mode must be set to 'control-group' or 'mixed'. Refusing." ); }); | ||||
579 | return -ENOEXEC8; | ||||
580 | } | ||||
581 | |||||
582 | if (s->usb_function_descriptors && !s->usb_function_strings) | ||||
583 | log_unit_warning(UNIT(s), "Service has USBFunctionDescriptors= setting, but no USBFunctionStrings=. Ignoring.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 583, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service has USBFunctionDescriptors= setting, but no USBFunctionStrings=. Ignoring." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 583, __func__, "Service has USBFunctionDescriptors= setting, but no USBFunctionStrings=. Ignoring." ); }); | ||||
584 | |||||
585 | if (!s->usb_function_descriptors && s->usb_function_strings) | ||||
586 | log_unit_warning(UNIT(s), "Service has USBFunctionStrings= setting, but no USBFunctionDescriptors=. Ignoring.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 586, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service has USBFunctionStrings= setting, but no USBFunctionDescriptors=. Ignoring." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 586, __func__, "Service has USBFunctionStrings= setting, but no USBFunctionDescriptors=. Ignoring." ); }); | ||||
587 | |||||
588 | if (s->runtime_max_usec != USEC_INFINITY((usec_t) -1) && s->type == SERVICE_ONESHOT) | ||||
589 | log_unit_warning(UNIT(s), "MaxRuntimeSec= has no effect in combination with Type=oneshot. Ignoring.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 589, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "MaxRuntimeSec= has no effect in combination with Type=oneshot. Ignoring." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 589, __func__, "MaxRuntimeSec= has no effect in combination with Type=oneshot. Ignoring." ); }); | ||||
590 | |||||
591 | return 0; | ||||
592 | } | ||||
593 | |||||
594 | static int service_add_default_dependencies(Service *s) { | ||||
595 | int r; | ||||
596 | |||||
597 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 597, __PRETTY_FUNCTION__ ); } while (0); | ||||
598 | |||||
599 | if (!UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->default_dependencies) | ||||
600 | return 0; | ||||
601 | |||||
602 | /* Add a number of automatic dependencies useful for the | ||||
603 | * majority of services. */ | ||||
604 | |||||
605 | if (MANAGER_IS_SYSTEM(UNIT(s)->manager)((({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager)->unit_file_scope == UNIT_FILE_SYSTEM )) { | ||||
606 | /* First, pull in the really early boot stuff, and | ||||
607 | * require it, so that we fail if we can't acquire | ||||
608 | * it. */ | ||||
609 | |||||
610 | r = unit_add_two_dependencies_by_name(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET"sysinit.target", NULL((void*)0), true1, UNIT_DEPENDENCY_DEFAULT); | ||||
611 | if (r < 0) | ||||
612 | return r; | ||||
613 | } else { | ||||
614 | |||||
615 | /* In the --user instance there's no sysinit.target, | ||||
616 | * in that case require basic.target instead. */ | ||||
617 | |||||
618 | r = unit_add_dependency_by_name(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_REQUIRES, SPECIAL_BASIC_TARGET"basic.target", NULL((void*)0), true1, UNIT_DEPENDENCY_DEFAULT); | ||||
619 | if (r < 0) | ||||
620 | return r; | ||||
621 | } | ||||
622 | |||||
623 | /* Second, if the rest of the base system is in the same | ||||
624 | * transaction, order us after it, but do not pull it in or | ||||
625 | * even require it. */ | ||||
626 | r = unit_add_dependency_by_name(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_AFTER, SPECIAL_BASIC_TARGET"basic.target", NULL((void*)0), true1, UNIT_DEPENDENCY_DEFAULT); | ||||
627 | if (r < 0) | ||||
628 | return r; | ||||
629 | |||||
630 | /* Third, add us in for normal shutdown. */ | ||||
631 | return unit_add_two_dependencies_by_name(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET"shutdown.target", NULL((void*)0), true1, UNIT_DEPENDENCY_DEFAULT); | ||||
632 | } | ||||
633 | |||||
634 | static void service_fix_output(Service *s) { | ||||
635 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 635, __PRETTY_FUNCTION__ ); } while (0); | ||||
636 | |||||
637 | /* If nothing has been explicitly configured, patch default output in. If input is socket/tty we avoid this | ||||
638 | * however, since in that case we want output to default to the same place as we read input from. */ | ||||
639 | |||||
640 | if (s->exec_context.std_error == EXEC_OUTPUT_INHERIT && | ||||
641 | s->exec_context.std_output == EXEC_OUTPUT_INHERIT && | ||||
642 | s->exec_context.std_input == EXEC_INPUT_NULL) | ||||
643 | s->exec_context.std_error = UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->default_std_error; | ||||
644 | |||||
645 | if (s->exec_context.std_output == EXEC_OUTPUT_INHERIT && | ||||
646 | s->exec_context.std_input == EXEC_INPUT_NULL) | ||||
647 | s->exec_context.std_output = UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->default_std_output; | ||||
648 | |||||
649 | if (s->exec_context.std_input == EXEC_INPUT_NULL && | ||||
650 | s->exec_context.stdin_data_size > 0) | ||||
651 | s->exec_context.std_input = EXEC_INPUT_DATA; | ||||
652 | } | ||||
653 | |||||
654 | static int service_setup_bus_name(Service *s) { | ||||
655 | int r; | ||||
656 | |||||
657 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 657, __PRETTY_FUNCTION__ ); } while (0); | ||||
658 | |||||
659 | if (!s->bus_name) | ||||
660 | return 0; | ||||
661 | |||||
662 | r = unit_add_dependency_by_name(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_REQUIRES, SPECIAL_DBUS_SOCKET"dbus.socket", NULL((void*)0), true1, UNIT_DEPENDENCY_FILE); | ||||
663 | if (r < 0) | ||||
664 | return log_unit_error_errno(UNIT(s), r, "Failed to add dependency on " SPECIAL_DBUS_SOCKET ": %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/service.c", 664, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to add dependency on " "dbus.socket" ": %m") : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((3))), r, "../src/core/service.c", 664, __func__ , "Failed to add dependency on " "dbus.socket" ": %m"); }); | ||||
665 | |||||
666 | /* We always want to be ordered against dbus.socket if both are in the transaction. */ | ||||
667 | r = unit_add_dependency_by_name(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT_AFTER, SPECIAL_DBUS_SOCKET"dbus.socket", NULL((void*)0), true1, UNIT_DEPENDENCY_FILE); | ||||
668 | if (r < 0) | ||||
669 | return log_unit_error_errno(UNIT(s), r, "Failed to add dependency on " SPECIAL_DBUS_SOCKET ": %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/service.c", 669, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to add dependency on " "dbus.socket" ": %m") : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((3))), r, "../src/core/service.c", 669, __func__ , "Failed to add dependency on " "dbus.socket" ": %m"); }); | ||||
670 | |||||
671 | r = unit_watch_bus_name(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), s->bus_name); | ||||
672 | if (r == -EEXIST17) | ||||
673 | return log_unit_error_errno(UNIT(s), r, "Two services allocated for the same bus name %s, refusing operation.", s->bus_name)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/service.c", 673, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Two services allocated for the same bus name %s, refusing operation." , s->bus_name) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/core/service.c", 673, __func__, "Two services allocated for the same bus name %s, refusing operation." , s->bus_name); }); | ||||
674 | if (r < 0) | ||||
675 | return log_unit_error_errno(UNIT(s), r, "Cannot watch bus name %s: %m", s->bus_name)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/service.c", 675, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Cannot watch bus name %s: %m" , s->bus_name) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/core/service.c", 675, __func__, "Cannot watch bus name %s: %m" , s->bus_name); }); | ||||
676 | |||||
677 | return 0; | ||||
678 | } | ||||
679 | |||||
680 | static int service_add_extras(Service *s) { | ||||
681 | int r; | ||||
682 | |||||
683 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 683, __PRETTY_FUNCTION__ ); } while (0); | ||||
684 | |||||
685 | if (s->type == _SERVICE_TYPE_INVALID) { | ||||
686 | /* Figure out a type automatically */ | ||||
687 | if (s->bus_name) | ||||
688 | s->type = SERVICE_DBUS; | ||||
689 | else if (s->exec_command[SERVICE_EXEC_START]) | ||||
690 | s->type = SERVICE_SIMPLE; | ||||
691 | else | ||||
692 | s->type = SERVICE_ONESHOT; | ||||
693 | } | ||||
694 | |||||
695 | /* Oneshot services have disabled start timeout by default */ | ||||
696 | if (s->type == SERVICE_ONESHOT && !s->start_timeout_defined) | ||||
697 | s->timeout_start_usec = USEC_INFINITY((usec_t) -1); | ||||
698 | |||||
699 | service_fix_output(s); | ||||
700 | |||||
701 | r = unit_patch_contexts(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
702 | if (r < 0) | ||||
703 | return r; | ||||
704 | |||||
705 | r = unit_add_exec_dependencies(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), &s->exec_context); | ||||
706 | if (r < 0) | ||||
707 | return r; | ||||
708 | |||||
709 | r = unit_set_default_slice(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
710 | if (r < 0) | ||||
711 | return r; | ||||
712 | |||||
713 | /* If the service needs the notify socket, let's enable it automatically. */ | ||||
714 | if (s->notify_access == NOTIFY_NONE && | ||||
715 | (s->type == SERVICE_NOTIFY || s->watchdog_usec > 0 || s->n_fd_store_max > 0)) | ||||
716 | s->notify_access = NOTIFY_MAIN; | ||||
717 | |||||
718 | r = service_add_default_dependencies(s); | ||||
719 | if (r < 0) | ||||
720 | return r; | ||||
721 | |||||
722 | r = service_setup_bus_name(s); | ||||
723 | if (r < 0) | ||||
724 | return r; | ||||
725 | |||||
726 | return 0; | ||||
727 | } | ||||
728 | |||||
729 | static int service_load(Unit *u) { | ||||
730 | Service *s = SERVICE(u); | ||||
731 | int r; | ||||
732 | |||||
733 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 733, __PRETTY_FUNCTION__ ); } while (0); | ||||
734 | |||||
735 | /* Load a .service file */ | ||||
736 | r = unit_load_fragment(u); | ||||
737 | if (r < 0) | ||||
738 | return r; | ||||
739 | |||||
740 | /* Still nothing found? Then let's give up */ | ||||
741 | if (u->load_state == UNIT_STUB) | ||||
742 | return -ENOENT2; | ||||
743 | |||||
744 | /* This is a new unit? Then let's add in some extras */ | ||||
745 | if (u->load_state == UNIT_LOADED) { | ||||
746 | |||||
747 | /* We were able to load something, then let's add in | ||||
748 | * the dropin directories. */ | ||||
749 | r = unit_load_dropin(u); | ||||
750 | if (r < 0) | ||||
751 | return r; | ||||
752 | |||||
753 | /* This is a new unit? Then let's add in some | ||||
754 | * extras */ | ||||
755 | r = service_add_extras(s); | ||||
756 | if (r < 0) | ||||
757 | return r; | ||||
758 | } | ||||
759 | |||||
760 | return service_verify(s); | ||||
761 | } | ||||
762 | |||||
763 | static void service_dump(Unit *u, FILE *f, const char *prefix) { | ||||
764 | char buf_restart[FORMAT_TIMESPAN_MAX64], buf_start[FORMAT_TIMESPAN_MAX64], buf_stop[FORMAT_TIMESPAN_MAX64]; | ||||
765 | char buf_runtime[FORMAT_TIMESPAN_MAX64], buf_watchdog[FORMAT_TIMESPAN_MAX64]; | ||||
766 | ServiceExecCommand c; | ||||
767 | Service *s = SERVICE(u); | ||||
768 | const char *prefix2; | ||||
769 | |||||
770 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 770, __PRETTY_FUNCTION__ ); } while (0); | ||||
771 | |||||
772 | prefix = strempty(prefix); | ||||
773 | prefix2 = strjoina(prefix, "\t")({ const char *_appendees_[] = { prefix, "\t" }; char *_d_, * _p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }); | ||||
774 | |||||
775 | fprintf(f, | ||||
776 | "%sService State: %s\n" | ||||
777 | "%sResult: %s\n" | ||||
778 | "%sReload Result: %s\n" | ||||
779 | "%sPermissionsStartOnly: %s\n" | ||||
780 | "%sRootDirectoryStartOnly: %s\n" | ||||
781 | "%sRemainAfterExit: %s\n" | ||||
782 | "%sGuessMainPID: %s\n" | ||||
783 | "%sType: %s\n" | ||||
784 | "%sRestart: %s\n" | ||||
785 | "%sNotifyAccess: %s\n" | ||||
786 | "%sNotifyState: %s\n", | ||||
787 | prefix, service_state_to_string(s->state), | ||||
788 | prefix, service_result_to_string(s->result), | ||||
789 | prefix, service_result_to_string(s->reload_result), | ||||
790 | prefix, yes_no(s->permissions_start_only), | ||||
791 | prefix, yes_no(s->root_directory_start_only), | ||||
792 | prefix, yes_no(s->remain_after_exit), | ||||
793 | prefix, yes_no(s->guess_main_pid), | ||||
794 | prefix, service_type_to_string(s->type), | ||||
795 | prefix, service_restart_to_string(s->restart), | ||||
796 | prefix, notify_access_to_string(s->notify_access), | ||||
797 | prefix, notify_state_to_string(s->notify_state)); | ||||
798 | |||||
799 | if (s->control_pid > 0) | ||||
800 | fprintf(f, | ||||
801 | "%sControl PID: "PID_FMT"%" "i""\n", | ||||
802 | prefix, s->control_pid); | ||||
803 | |||||
804 | if (s->main_pid > 0) | ||||
805 | fprintf(f, | ||||
806 | "%sMain PID: "PID_FMT"%" "i""\n" | ||||
807 | "%sMain PID Known: %s\n" | ||||
808 | "%sMain PID Alien: %s\n", | ||||
809 | prefix, s->main_pid, | ||||
810 | prefix, yes_no(s->main_pid_known), | ||||
811 | prefix, yes_no(s->main_pid_alien)); | ||||
812 | |||||
813 | if (s->pid_file) | ||||
814 | fprintf(f, | ||||
815 | "%sPIDFile: %s\n", | ||||
816 | prefix, s->pid_file); | ||||
817 | |||||
818 | if (s->bus_name) | ||||
819 | fprintf(f, | ||||
820 | "%sBusName: %s\n" | ||||
821 | "%sBus Name Good: %s\n", | ||||
822 | prefix, s->bus_name, | ||||
823 | prefix, yes_no(s->bus_name_good)); | ||||
824 | |||||
825 | if (UNIT_ISSET(s->accept_socket)(!!(s->accept_socket).target)) | ||||
826 | fprintf(f, | ||||
827 | "%sAccept Socket: %s\n", | ||||
828 | prefix, UNIT_DEREF(s->accept_socket)((s->accept_socket).target)->id); | ||||
829 | |||||
830 | fprintf(f, | ||||
831 | "%sRestartSec: %s\n" | ||||
832 | "%sTimeoutStartSec: %s\n" | ||||
833 | "%sTimeoutStopSec: %s\n" | ||||
834 | "%sRuntimeMaxSec: %s\n" | ||||
835 | "%sWatchdogSec: %s\n", | ||||
836 | prefix, format_timespan(buf_restart, sizeof(buf_restart), s->restart_usec, USEC_PER_SEC((usec_t) 1000000ULL)), | ||||
837 | prefix, format_timespan(buf_start, sizeof(buf_start), s->timeout_start_usec, USEC_PER_SEC((usec_t) 1000000ULL)), | ||||
838 | prefix, format_timespan(buf_stop, sizeof(buf_stop), s->timeout_stop_usec, USEC_PER_SEC((usec_t) 1000000ULL)), | ||||
839 | prefix, format_timespan(buf_runtime, sizeof(buf_runtime), s->runtime_max_usec, USEC_PER_SEC((usec_t) 1000000ULL)), | ||||
840 | prefix, format_timespan(buf_watchdog, sizeof(buf_watchdog), s->watchdog_usec, USEC_PER_SEC((usec_t) 1000000ULL))); | ||||
841 | |||||
842 | kill_context_dump(&s->kill_context, f, prefix); | ||||
843 | exec_context_dump(&s->exec_context, f, prefix); | ||||
844 | |||||
845 | for (c = 0; c < _SERVICE_EXEC_COMMAND_MAX; c++) { | ||||
846 | |||||
847 | if (!s->exec_command[c]) | ||||
848 | continue; | ||||
849 | |||||
850 | fprintf(f, "%s-> %s:\n", | ||||
851 | prefix, service_exec_command_to_string(c)); | ||||
852 | |||||
853 | exec_command_dump_list(s->exec_command[c], f, prefix2); | ||||
854 | } | ||||
855 | |||||
856 | if (s->status_text) | ||||
857 | fprintf(f, "%sStatus Text: %s\n", | ||||
858 | prefix, s->status_text); | ||||
859 | |||||
860 | if (s->n_fd_store_max > 0) | ||||
861 | fprintf(f, | ||||
862 | "%sFile Descriptor Store Max: %u\n" | ||||
863 | "%sFile Descriptor Store Current: %zu\n", | ||||
864 | prefix, s->n_fd_store_max, | ||||
865 | prefix, s->n_fd_store); | ||||
866 | |||||
867 | cgroup_context_dump(&s->cgroup_context, f, prefix); | ||||
868 | } | ||||
869 | |||||
870 | static int service_is_suitable_main_pid(Service *s, pid_t pid, int prio) { | ||||
871 | Unit *owner; | ||||
872 | |||||
873 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 873, __PRETTY_FUNCTION__ ); } while (0); | ||||
874 | assert(pid_is_valid(pid))do { if ((__builtin_expect(!!(!(pid_is_valid(pid))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("pid_is_valid(pid)"), "../src/core/service.c" , 874, __PRETTY_FUNCTION__); } while (0); | ||||
875 | |||||
876 | /* Checks whether the specified PID is suitable as main PID for this service. returns negative if not, 0 if the | ||||
877 | * PID is questionnable but should be accepted if the source of configuration is trusted. > 0 if the PID is | ||||
878 | * good */ | ||||
879 | |||||
880 | if (pid == getpid_cached() || pid == 1) { | ||||
881 | log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" is the manager, refusing.", pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (prio, 0, "../src/core/service.c", 881, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "New main PID ""%" "i"" is the manager, refusing." , pid) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((prio))), 0, "../src/core/service.c", 881, __func__, "New main PID " "%" "i"" is the manager, refusing.", pid); }); | ||||
882 | return -EPERM1; | ||||
883 | } | ||||
884 | |||||
885 | if (pid == s->control_pid) { | ||||
886 | log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" is the control process, refusing.", pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (prio, 0, "../src/core/service.c", 886, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "New main PID ""%" "i"" is the control process, refusing." , pid) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((prio))), 0, "../src/core/service.c", 886, __func__, "New main PID " "%" "i"" is the control process, refusing.", pid); }); | ||||
887 | return -EPERM1; | ||||
888 | } | ||||
889 | |||||
890 | if (!pid_is_alive(pid)) { | ||||
891 | log_unit_full(UNIT(s), prio, 0, "New main PID "PID_FMT" does not exist or is a zombie.", pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (prio, 0, "../src/core/service.c", 891, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "New main PID ""%" "i"" does not exist or is a zombie." , pid) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((prio))), 0, "../src/core/service.c", 891, __func__, "New main PID " "%" "i"" does not exist or is a zombie.", pid); }); | ||||
892 | return -ESRCH3; | ||||
893 | } | ||||
894 | |||||
895 | owner = manager_get_unit_by_pid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager, pid); | ||||
896 | if (owner == UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })) { | ||||
897 | log_unit_debug(UNIT(s), "New main PID "PID_FMT" belongs to service, we are happy.", pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 897, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "New main PID ""%" "i"" belongs to service, we are happy." , pid) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 897, __func__, "New main PID " "%" "i"" belongs to service, we are happy.", pid); }); | ||||
898 | return 1; /* Yay, it's definitely a good PID */ | ||||
899 | } | ||||
900 | |||||
901 | return 0; /* Hmm it's a suspicious PID, let's accept it if configuration source is trusted */ | ||||
902 | } | ||||
903 | |||||
904 | static int service_load_pid_file(Service *s, bool_Bool may_warn) { | ||||
905 | char procfs[STRLEN("/proc/self/fd/")(sizeof("""/proc/self/fd/""") - 1) + DECIMAL_STR_MAX(int)(2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof (int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof(int[-2 *(sizeof(int) > 8)])))]; | ||||
906 | bool_Bool questionable_pid_file = false0; | ||||
907 | _cleanup_free___attribute__((cleanup(freep))) char *k = NULL((void*)0); | ||||
908 | _cleanup_close___attribute__((cleanup(closep))) int fd = -1; | ||||
909 | int r, prio; | ||||
910 | pid_t pid; | ||||
911 | |||||
912 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 912, __PRETTY_FUNCTION__ ); } while (0); | ||||
913 | |||||
914 | if (!s->pid_file) | ||||
915 | return -ENOENT2; | ||||
916 | |||||
917 | prio = may_warn ? LOG_INFO6 : LOG_DEBUG7; | ||||
918 | |||||
919 | fd = chase_symlinks(s->pid_file, NULL((void*)0), CHASE_OPEN|CHASE_SAFE, NULL((void*)0)); | ||||
920 | if (fd == -EPERM1) { | ||||
921 | log_unit_full(UNIT(s), LOG_DEBUG, fd, "Permission denied while opening PID file or potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, fd, "../src/core/service.c", 921, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Permission denied while opening PID file or potentially unsafe symlink chain, will now retry with relaxed checks: %s" , s->pid_file) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), fd, "../src/core/service.c", 921, __func__, "Permission denied while opening PID file or potentially unsafe symlink chain, will now retry with relaxed checks: %s" , s->pid_file); }); | ||||
922 | |||||
923 | questionable_pid_file = true1; | ||||
924 | |||||
925 | fd = chase_symlinks(s->pid_file, NULL((void*)0), CHASE_OPEN, NULL((void*)0)); | ||||
926 | } | ||||
927 | if (fd < 0) | ||||
928 | return log_unit_full(UNIT(s), prio, fd, "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state))({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (prio, fd, "../src/core/service.c", 928, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Can't open PID file %s (yet?) after %s: %m" , s->pid_file, service_state_to_string(s->state)) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((prio))), fd, "../src/core/service.c" , 928, __func__, "Can't open PID file %s (yet?) after %s: %m" , s->pid_file, service_state_to_string(s->state)); }); | ||||
929 | |||||
930 | /* Let's read the PID file now that we chased it down. But we need to convert the O_PATH fd chase_symlinks() returned us into a proper fd first. */ | ||||
931 | xsprintf(procfs, "/proc/self/fd/%i", fd)do { if ((__builtin_expect(!!(!(((size_t) snprintf(procfs, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (procfs), typeof(&*(procfs))), sizeof(procfs)/sizeof((procfs )[0]), ((void)0))), "/proc/self/fd/%i", fd) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (procfs), typeof(&*(procfs))), sizeof(procfs)/sizeof((procfs )[0]), ((void)0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("xsprintf: " "procfs" "[] must be big enough"), "../src/core/service.c" , 931, __PRETTY_FUNCTION__); } while (0); | ||||
932 | r = read_one_line_file(procfs, &k); | ||||
933 | if (r < 0) | ||||
934 | return log_unit_error_errno(UNIT(s), r, "Can't convert PID files %s O_PATH file descriptor to proper file descriptor: %m", s->pid_file)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/service.c", 934, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Can't convert PID files %s O_PATH file descriptor to proper file descriptor: %m" , s->pid_file) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/core/service.c", 934, __func__, "Can't convert PID files %s O_PATH file descriptor to proper file descriptor: %m" , s->pid_file); }); | ||||
935 | |||||
936 | r = parse_pid(k, &pid); | ||||
937 | if (r < 0) | ||||
938 | return log_unit_full(UNIT(s), prio, r, "Failed to parse PID from file %s: %m", s->pid_file)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (prio, r, "../src/core/service.c", 938, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to parse PID from file %s: %m" , s->pid_file) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((prio))), r, "../src/core/service.c", 938, __func__, "Failed to parse PID from file %s: %m" , s->pid_file); }); | ||||
939 | |||||
940 | if (s->main_pid_known && pid == s->main_pid) | ||||
941 | return 0; | ||||
942 | |||||
943 | r = service_is_suitable_main_pid(s, pid, prio); | ||||
944 | if (r < 0) | ||||
945 | return r; | ||||
946 | if (r == 0) { | ||||
947 | struct stat st; | ||||
948 | |||||
949 | if (questionable_pid_file) { | ||||
950 | log_unit_error(UNIT(s), "Refusing to accept PID outside of service control group, acquired through unsafe symlink chain: %s", s->pid_file)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/service.c", 950, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Refusing to accept PID outside of service control group, acquired through unsafe symlink chain: %s" , s->pid_file) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))), 0, "../src/core/service.c", 950, __func__, "Refusing to accept PID outside of service control group, acquired through unsafe symlink chain: %s" , s->pid_file); }); | ||||
951 | return -EPERM1; | ||||
952 | } | ||||
953 | |||||
954 | /* Hmm, it's not clear if the new main PID is safe. Let's allow this if the PID file is owned by root */ | ||||
955 | |||||
956 | if (fstat(fd, &st) < 0) | ||||
957 | return log_unit_error_errno(UNIT(s), errno, "Failed to fstat() PID file O_PATH fd: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, (*__errno_location ()), "../src/core/service.c", 957, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "Failed to fstat() PID file O_PATH fd: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), (*__errno_location ()), "../src/core/service.c", 957, __func__ , "Failed to fstat() PID file O_PATH fd: %m"); }); | ||||
958 | |||||
959 | if (st.st_uid != 0) { | ||||
960 | log_unit_error(UNIT(s), "New main PID "PID_FMT" does not belong to service, and PID file is not owned by root. Refusing.", pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/service.c", 960, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "New main PID ""%" "i"" does not belong to service, and PID file is not owned by root. Refusing." , pid) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3))), 0, "../src/core/service.c", 960, __func__, "New main PID " "%" "i"" does not belong to service, and PID file is not owned by root. Refusing." , pid); }); | ||||
961 | return -EPERM1; | ||||
962 | } | ||||
963 | |||||
964 | log_unit_debug(UNIT(s), "New main PID "PID_FMT" does not belong to service, but we'll accept it since PID file is owned by root.", pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 964, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "New main PID ""%" "i"" does not belong to service, but we'll accept it since PID file is owned by root." , pid) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 964, __func__, "New main PID " "%" "i"" does not belong to service, but we'll accept it since PID file is owned by root." , pid); }); | ||||
965 | } | ||||
966 | |||||
967 | if (s->main_pid_known) { | ||||
968 | log_unit_debug(UNIT(s), "Main PID changing: "PID_FMT" -> "PID_FMT, s->main_pid, pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 968, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Main PID changing: ""%" "i"" -> " "%" "i", s->main_pid, pid) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((7))), 0, "../src/core/service.c", 968, __func__ , "Main PID changing: ""%" "i"" -> ""%" "i", s->main_pid , pid); }); | ||||
969 | |||||
970 | service_unwatch_main_pid(s); | ||||
971 | s->main_pid_known = false0; | ||||
972 | } else | ||||
973 | log_unit_debug(UNIT(s), "Main PID loaded: "PID_FMT, pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 973, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Main PID loaded: ""%" "i", pid ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7 ))), 0, "../src/core/service.c", 973, __func__, "Main PID loaded: " "%" "i", pid); }); | ||||
974 | |||||
975 | r = service_set_main_pid(s, pid); | ||||
976 | if (r < 0) | ||||
977 | return r; | ||||
978 | |||||
979 | r = unit_watch_pid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), pid, false0); | ||||
980 | if (r < 0) /* FIXME: we need to do something here */ | ||||
981 | return log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" for service: %m", pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 981, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to watch PID ""%" "i"" for service: %m" , pid) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/core/service.c", 981, __func__, "Failed to watch PID " "%" "i"" for service: %m", pid); }); | ||||
982 | |||||
983 | return 1; | ||||
984 | } | ||||
985 | |||||
986 | static void service_search_main_pid(Service *s) { | ||||
987 | pid_t pid = 0; | ||||
988 | int r; | ||||
989 | |||||
990 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 990, __PRETTY_FUNCTION__ ); } while (0); | ||||
991 | |||||
992 | /* If we know it anyway, don't ever fallback to unreliable | ||||
993 | * heuristics */ | ||||
994 | if (s->main_pid_known) | ||||
995 | return; | ||||
996 | |||||
997 | if (!s->guess_main_pid) | ||||
998 | return; | ||||
999 | |||||
1000 | assert(s->main_pid <= 0)do { if ((__builtin_expect(!!(!(s->main_pid <= 0)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->main_pid <= 0" ), "../src/core/service.c", 1000, __PRETTY_FUNCTION__); } while (0); | ||||
1001 | |||||
1002 | if (unit_search_main_pid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), &pid) < 0) | ||||
1003 | return; | ||||
1004 | |||||
1005 | log_unit_debug(UNIT(s), "Main PID guessed: "PID_FMT, pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 1005, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Main PID guessed: ""%" "i", pid ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7 ))), 0, "../src/core/service.c", 1005, __func__, "Main PID guessed: " "%" "i", pid); }); | ||||
1006 | if (service_set_main_pid(s, pid) < 0) | ||||
1007 | return; | ||||
1008 | |||||
1009 | r = unit_watch_pid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), pid, false0); | ||||
1010 | if (r < 0) | ||||
1011 | /* FIXME: we need to do something here */ | ||||
1012 | log_unit_warning_errno(UNIT(s), r, "Failed to watch PID "PID_FMT" from: %m", pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 1012, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to watch PID ""%" "i"" from: %m" , pid) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4))), r, "../src/core/service.c", 1012, __func__, "Failed to watch PID " "%" "i"" from: %m", pid); }); | ||||
1013 | } | ||||
1014 | |||||
1015 | static void service_set_state(Service *s, ServiceState state) { | ||||
1016 | ServiceState old_state; | ||||
1017 | const UnitActiveState *table; | ||||
1018 | |||||
1019 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1019, __PRETTY_FUNCTION__ ); } while (0); | ||||
1020 | |||||
1021 | table = s->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table; | ||||
1022 | |||||
1023 | old_state = s->state; | ||||
1024 | s->state = state; | ||||
1025 | |||||
1026 | service_unwatch_pid_file(s); | ||||
1027 | |||||
1028 | if (!IN_SET(state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL , SERVICE_AUTO_RESTART})/sizeof(int)]; switch(state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : case SERVICE_AUTO_RESTART: _found = 1; break; default: break ; } _found; }) | ||||
1029 | SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL , SERVICE_AUTO_RESTART})/sizeof(int)]; switch(state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : case SERVICE_AUTO_RESTART: _found = 1; break; default: break ; } _found; }) | ||||
1030 | SERVICE_RUNNING,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL , SERVICE_AUTO_RESTART})/sizeof(int)]; switch(state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : case SERVICE_AUTO_RESTART: _found = 1; break; default: break ; } _found; }) | ||||
1031 | SERVICE_RELOAD,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL , SERVICE_AUTO_RESTART})/sizeof(int)]; switch(state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : case SERVICE_AUTO_RESTART: _found = 1; break; default: break ; } _found; }) | ||||
1032 | SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL , SERVICE_AUTO_RESTART})/sizeof(int)]; switch(state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : case SERVICE_AUTO_RESTART: _found = 1; break; default: break ; } _found; }) | ||||
1033 | SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL , SERVICE_AUTO_RESTART})/sizeof(int)]; switch(state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : case SERVICE_AUTO_RESTART: _found = 1; break; default: break ; } _found; }) | ||||
1034 | SERVICE_AUTO_RESTART)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL , SERVICE_AUTO_RESTART})/sizeof(int)]; switch(state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : case SERVICE_AUTO_RESTART: _found = 1; break; default: break ; } _found; })) | ||||
1035 | s->timer_event_source = sd_event_source_unref(s->timer_event_source); | ||||
1036 | |||||
1037 | if (!IN_SET(state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(state) { case SERVICE_START : case SERVICE_START_POST: case SERVICE_RUNNING: case SERVICE_RELOAD : case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
1038 | SERVICE_START, SERVICE_START_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(state) { case SERVICE_START : case SERVICE_START_POST: case SERVICE_RUNNING: case SERVICE_RELOAD : case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
1039 | SERVICE_RUNNING, SERVICE_RELOAD,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(state) { case SERVICE_START : case SERVICE_START_POST: case SERVICE_RUNNING: case SERVICE_RELOAD : case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
1040 | SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(state) { case SERVICE_START : case SERVICE_START_POST: case SERVICE_RUNNING: case SERVICE_RELOAD : case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
1041 | SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(state) { case SERVICE_START : case SERVICE_START_POST: case SERVICE_RUNNING: case SERVICE_RELOAD : case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; })) { | ||||
1042 | service_unwatch_main_pid(s); | ||||
1043 | s->main_command = NULL((void*)0); | ||||
1044 | } | ||||
1045 | |||||
1046 | if (!IN_SET(state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT , SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST , SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL})/sizeof(int)] ; switch(state) { case SERVICE_CONDITION: case SERVICE_START_PRE : case SERVICE_START: case SERVICE_START_POST: case SERVICE_RELOAD : case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
1047 | SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT , SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST , SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL})/sizeof(int)] ; switch(state) { case SERVICE_CONDITION: case SERVICE_START_PRE : case SERVICE_START: case SERVICE_START_POST: case SERVICE_RELOAD : case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
1048 | SERVICE_RELOAD,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT , SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST , SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL})/sizeof(int)] ; switch(state) { case SERVICE_CONDITION: case SERVICE_START_PRE : case SERVICE_START: case SERVICE_START_POST: case SERVICE_RELOAD : case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
1049 | SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT , SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST , SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL})/sizeof(int)] ; switch(state) { case SERVICE_CONDITION: case SERVICE_START_PRE : case SERVICE_START: case SERVICE_START_POST: case SERVICE_RELOAD : case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
1050 | SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT , SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST , SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL})/sizeof(int)] ; switch(state) { case SERVICE_CONDITION: case SERVICE_START_PRE : case SERVICE_START: case SERVICE_START_POST: case SERVICE_RELOAD : case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; })) { | ||||
1051 | service_unwatch_control_pid(s); | ||||
1052 | s->control_command = NULL((void*)0); | ||||
1053 | s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; | ||||
1054 | } | ||||
1055 | |||||
1056 | if (IN_SET(state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART })/sizeof(int)]; switch(state) { case SERVICE_DEAD: case SERVICE_FAILED : case SERVICE_AUTO_RESTART: _found = 1; break; default: break ; } _found; })) { | ||||
1057 | unit_unwatch_all_pids(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
1058 | unit_dequeue_rewatch_pids(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
1059 | } | ||||
1060 | |||||
1061 | if (!IN_SET(state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(state) { case SERVICE_CONDITION: case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
1062 | SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(state) { case SERVICE_CONDITION: case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
1063 | SERVICE_RUNNING, SERVICE_RELOAD,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(state) { case SERVICE_CONDITION: case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
1064 | SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(state) { case SERVICE_CONDITION: case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
1065 | SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(state) { case SERVICE_CONDITION: case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) && | ||||
1066 | !(state == SERVICE_DEAD && UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->job)) | ||||
1067 | service_close_socket_fd(s); | ||||
1068 | |||||
1069 | if (state != SERVICE_START) | ||||
1070 | s->exec_fd_event_source = sd_event_source_unref(s->exec_fd_event_source); | ||||
1071 | |||||
1072 | if (!IN_SET(state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD })/sizeof(int)]; switch(state) { case SERVICE_START_POST: case SERVICE_RUNNING: case SERVICE_RELOAD: _found = 1; break; default : break; } _found; })) | ||||
1073 | service_stop_watchdog(s); | ||||
1074 | |||||
1075 | /* For the inactive states unit_notify() will trim the cgroup, | ||||
1076 | * but for exit we have to do that ourselves... */ | ||||
1077 | if (state == SERVICE_EXITED && !MANAGER_IS_RELOADING(UNIT(s)->manager)((({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager)->n_reloading > 0)) | ||||
1078 | unit_prune_cgroup(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
1079 | |||||
1080 | if (old_state != state) | ||||
1081 | log_unit_debug(UNIT(s), "Changed %s -> %s", service_state_to_string(old_state), service_state_to_string(state))({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 1081, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Changed %s -> %s", service_state_to_string (old_state), service_state_to_string(state)) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 1081, __func__, "Changed %s -> %s", service_state_to_string (old_state), service_state_to_string(state)); }); | ||||
1082 | |||||
1083 | unit_notify(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), table[old_state], table[state], | ||||
1084 | (s->reload_result == SERVICE_SUCCESS ? 0 : UNIT_NOTIFY_RELOAD_FAILURE) | | ||||
1085 | (s->will_auto_restart ? UNIT_NOTIFY_WILL_AUTO_RESTART : 0) | | ||||
1086 | (s->result == SERVICE_SKIP_CONDITION ? UNIT_NOTIFY_SKIP_CONDITION : 0)); | ||||
1087 | } | ||||
1088 | |||||
1089 | static usec_t service_coldplug_timeout(Service *s) { | ||||
1090 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1090, __PRETTY_FUNCTION__ ); } while (0); | ||||
1091 | |||||
1092 | switch (s->deserialized_state) { | ||||
1093 | |||||
1094 | case SERVICE_CONDITION: | ||||
1095 | case SERVICE_START_PRE: | ||||
1096 | case SERVICE_START: | ||||
1097 | case SERVICE_START_POST: | ||||
1098 | case SERVICE_RELOAD: | ||||
1099 | return usec_add(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->state_change_timestamp.monotonic, s->timeout_start_usec); | ||||
1100 | |||||
1101 | case SERVICE_RUNNING: | ||||
1102 | return usec_add(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->active_enter_timestamp.monotonic, s->runtime_max_usec); | ||||
1103 | |||||
1104 | case SERVICE_STOP: | ||||
1105 | case SERVICE_STOP_SIGABRT: | ||||
1106 | case SERVICE_STOP_SIGTERM: | ||||
1107 | case SERVICE_STOP_SIGKILL: | ||||
1108 | case SERVICE_STOP_POST: | ||||
1109 | case SERVICE_FINAL_SIGTERM: | ||||
1110 | case SERVICE_FINAL_SIGKILL: | ||||
1111 | return usec_add(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->state_change_timestamp.monotonic, s->timeout_stop_usec); | ||||
1112 | |||||
1113 | case SERVICE_AUTO_RESTART: | ||||
1114 | return usec_add(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->inactive_enter_timestamp.monotonic, s->restart_usec); | ||||
1115 | |||||
1116 | default: | ||||
1117 | return USEC_INFINITY((usec_t) -1); | ||||
1118 | } | ||||
1119 | } | ||||
1120 | |||||
1121 | static int service_coldplug(Unit *u) { | ||||
1122 | Service *s = SERVICE(u); | ||||
1123 | int r; | ||||
1124 | |||||
1125 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1125, __PRETTY_FUNCTION__ ); } while (0); | ||||
1126 | assert(s->state == SERVICE_DEAD)do { if ((__builtin_expect(!!(!(s->state == SERVICE_DEAD)) ,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->state == SERVICE_DEAD" ), "../src/core/service.c", 1126, __PRETTY_FUNCTION__); } while (0); | ||||
1127 | |||||
1128 | if (s->deserialized_state == s->state) | ||||
1129 | return 0; | ||||
1130 | |||||
1131 | r = service_arm_timer(s, service_coldplug_timeout(s)); | ||||
1132 | if (r < 0) | ||||
1133 | return r; | ||||
1134 | |||||
1135 | if (s->main_pid > 0 && | ||||
1136 | pid_is_unwaited(s->main_pid) && | ||||
1137 | (IN_SET(s->deserialized_state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(s->deserialized_state ) { case SERVICE_START: case SERVICE_START_POST: case SERVICE_RUNNING : case SERVICE_RELOAD: case SERVICE_STOP: case SERVICE_STOP_SIGABRT : case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST : case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break; } _found; }) | ||||
1138 | SERVICE_START, SERVICE_START_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(s->deserialized_state ) { case SERVICE_START: case SERVICE_START_POST: case SERVICE_RUNNING : case SERVICE_RELOAD: case SERVICE_STOP: case SERVICE_STOP_SIGABRT : case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST : case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break; } _found; }) | ||||
1139 | SERVICE_RUNNING, SERVICE_RELOAD,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(s->deserialized_state ) { case SERVICE_START: case SERVICE_START_POST: case SERVICE_RUNNING : case SERVICE_RELOAD: case SERVICE_STOP: case SERVICE_STOP_SIGABRT : case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST : case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break; } _found; }) | ||||
1140 | SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(s->deserialized_state ) { case SERVICE_START: case SERVICE_START_POST: case SERVICE_RUNNING : case SERVICE_RELOAD: case SERVICE_STOP: case SERVICE_STOP_SIGABRT : case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST : case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break; } _found; }) | ||||
1141 | SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(s->deserialized_state ) { case SERVICE_START: case SERVICE_START_POST: case SERVICE_RUNNING : case SERVICE_RELOAD: case SERVICE_STOP: case SERVICE_STOP_SIGABRT : case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST : case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break; } _found; }))) { | ||||
1142 | r = unit_watch_pid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), s->main_pid, false0); | ||||
1143 | if (r < 0) | ||||
1144 | return r; | ||||
1145 | } | ||||
1146 | |||||
1147 | if (s->control_pid > 0 && | ||||
1148 | pid_is_unwaited(s->control_pid) && | ||||
1149 | IN_SET(s->deserialized_state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT , SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST , SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL})/sizeof(int)] ; switch(s->deserialized_state) { case SERVICE_CONDITION: case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RELOAD: case SERVICE_STOP: case SERVICE_STOP_SIGABRT : case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST : case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break; } _found; }) | ||||
1150 | SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT , SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST , SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL})/sizeof(int)] ; switch(s->deserialized_state) { case SERVICE_CONDITION: case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RELOAD: case SERVICE_STOP: case SERVICE_STOP_SIGABRT : case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST : case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break; } _found; }) | ||||
1151 | SERVICE_RELOAD,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT , SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST , SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL})/sizeof(int)] ; switch(s->deserialized_state) { case SERVICE_CONDITION: case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RELOAD: case SERVICE_STOP: case SERVICE_STOP_SIGABRT : case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST : case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break; } _found; }) | ||||
1152 | SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT , SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST , SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL})/sizeof(int)] ; switch(s->deserialized_state) { case SERVICE_CONDITION: case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RELOAD: case SERVICE_STOP: case SERVICE_STOP_SIGABRT : case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST : case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break; } _found; }) | ||||
1153 | SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RELOAD, SERVICE_STOP, SERVICE_STOP_SIGABRT , SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST , SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL})/sizeof(int)] ; switch(s->deserialized_state) { case SERVICE_CONDITION: case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RELOAD: case SERVICE_STOP: case SERVICE_STOP_SIGABRT : case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST : case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break; } _found; })) { | ||||
1154 | r = unit_watch_pid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), s->control_pid, false0); | ||||
1155 | if (r < 0) | ||||
1156 | return r; | ||||
1157 | } | ||||
1158 | |||||
1159 | if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART })/sizeof(int)]; switch(s->deserialized_state) { case SERVICE_DEAD : case SERVICE_FAILED: case SERVICE_AUTO_RESTART: _found = 1; break; default: break; } _found; })) { | ||||
1160 | (void) unit_enqueue_rewatch_pids(u); | ||||
1161 | (void) unit_setup_dynamic_creds(u); | ||||
1162 | (void) unit_setup_exec_runtime(u); | ||||
1163 | } | ||||
1164 | |||||
1165 | if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD })/sizeof(int)]; switch(s->deserialized_state) { case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: _found = 1; break ; default: break; } _found; })) | ||||
1166 | service_start_watchdog(s); | ||||
1167 | |||||
1168 | if (UNIT_ISSET(s->accept_socket)(!!(s->accept_socket).target)) { | ||||
1169 | Socket* socket = SOCKET(UNIT_DEREF(s->accept_socket)((s->accept_socket).target)); | ||||
1170 | |||||
1171 | if (socket->max_connections_per_source > 0) { | ||||
1172 | SocketPeer *peer; | ||||
1173 | |||||
1174 | /* Make a best-effort attempt at bumping the connection count */ | ||||
1175 | if (socket_acquire_peer(socket, s->socket_fd, &peer) > 0) { | ||||
1176 | socket_peer_unref(s->peer); | ||||
1177 | s->peer = peer; | ||||
1178 | } | ||||
1179 | } | ||||
1180 | } | ||||
1181 | |||||
1182 | service_set_state(s, s->deserialized_state); | ||||
1183 | return 0; | ||||
1184 | } | ||||
1185 | |||||
1186 | static int service_collect_fds( | ||||
1187 | Service *s, | ||||
1188 | int **fds, | ||||
1189 | char ***fd_names, | ||||
1190 | size_t *n_socket_fds, | ||||
1191 | size_t *n_storage_fds) { | ||||
1192 | |||||
1193 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **rfd_names = NULL((void*)0); | ||||
1194 | _cleanup_free___attribute__((cleanup(freep))) int *rfds = NULL((void*)0); | ||||
1195 | size_t rn_socket_fds = 0, rn_storage_fds = 0; | ||||
1196 | int r; | ||||
1197 | |||||
1198 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1198, __PRETTY_FUNCTION__ ); } while (0); | ||||
1199 | assert(fds)do { if ((__builtin_expect(!!(!(fds)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fds"), "../src/core/service.c", 1199, __PRETTY_FUNCTION__ ); } while (0); | ||||
1200 | assert(fd_names)do { if ((__builtin_expect(!!(!(fd_names)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd_names"), "../src/core/service.c", 1200 , __PRETTY_FUNCTION__); } while (0); | ||||
1201 | assert(n_socket_fds)do { if ((__builtin_expect(!!(!(n_socket_fds)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("n_socket_fds"), "../src/core/service.c" , 1201, __PRETTY_FUNCTION__); } while (0); | ||||
1202 | assert(n_storage_fds)do { if ((__builtin_expect(!!(!(n_storage_fds)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("n_storage_fds"), "../src/core/service.c" , 1202, __PRETTY_FUNCTION__); } while (0); | ||||
1203 | |||||
1204 | if (s->socket_fd >= 0) { | ||||
1205 | |||||
1206 | /* Pass the per-connection socket */ | ||||
1207 | |||||
1208 | rfds = new(int, 1)((int*) malloc_multiply(sizeof(int), (1))); | ||||
1209 | if (!rfds) | ||||
1210 | return -ENOMEM12; | ||||
1211 | rfds[0] = s->socket_fd; | ||||
1212 | |||||
1213 | rfd_names = strv_new("connection", NULL((void*)0)); | ||||
1214 | if (!rfd_names) | ||||
1215 | return -ENOMEM12; | ||||
1216 | |||||
1217 | rn_socket_fds = 1; | ||||
1218 | } else { | ||||
1219 | Iterator i; | ||||
1220 | void *v; | ||||
1221 | Unit *u; | ||||
1222 | |||||
1223 | /* Pass all our configured sockets for singleton services */ | ||||
1224 | |||||
1225 | HASHMAP_FOREACH_KEY(v, u, UNIT(s)->dependencies[UNIT_TRIGGERED_BY], i)for ((i) = ((Iterator) { .idx = ((2147483647 *2U +1U) - 1), . next_key = ((void*)0) }); hashmap_iterate((({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_ ; })->dependencies[UNIT_TRIGGERED_BY]), &(i), (void**) &(v), (const void**) &(u)); ) { | ||||
1226 | _cleanup_free___attribute__((cleanup(freep))) int *cfds = NULL((void*)0); | ||||
1227 | Socket *sock; | ||||
1228 | int cn_fds; | ||||
1229 | |||||
1230 | if (u->type != UNIT_SOCKET) | ||||
1231 | continue; | ||||
1232 | |||||
1233 | sock = SOCKET(u); | ||||
1234 | |||||
1235 | cn_fds = socket_collect_fds(sock, &cfds); | ||||
1236 | if (cn_fds < 0) | ||||
1237 | return cn_fds; | ||||
1238 | |||||
1239 | if (cn_fds <= 0) | ||||
1240 | continue; | ||||
1241 | |||||
1242 | if (!rfds) { | ||||
1243 | rfds = TAKE_PTR(cfds)({ typeof(cfds) _ptr_ = (cfds); (cfds) = ((void*)0); _ptr_; } ); | ||||
1244 | rn_socket_fds = cn_fds; | ||||
1245 | } else { | ||||
1246 | int *t; | ||||
1247 | |||||
1248 | t = reallocarray(rfds, rn_socket_fds + cn_fds, sizeof(int)); | ||||
1249 | if (!t) | ||||
1250 | return -ENOMEM12; | ||||
1251 | |||||
1252 | memcpy(t + rn_socket_fds, cfds, cn_fds * sizeof(int)); | ||||
1253 | |||||
1254 | rfds = t; | ||||
1255 | rn_socket_fds += cn_fds; | ||||
1256 | } | ||||
1257 | |||||
1258 | r = strv_extend_n(&rfd_names, socket_fdname(sock), cn_fds); | ||||
1259 | if (r < 0) | ||||
1260 | return r; | ||||
1261 | } | ||||
1262 | } | ||||
1263 | |||||
1264 | if (s->n_fd_store > 0) { | ||||
1265 | ServiceFDStore *fs; | ||||
1266 | size_t n_fds; | ||||
1267 | char **nl; | ||||
1268 | int *t; | ||||
1269 | |||||
1270 | t = reallocarray(rfds, rn_socket_fds + s->n_fd_store, sizeof(int)); | ||||
1271 | if (!t) | ||||
1272 | return -ENOMEM12; | ||||
1273 | |||||
1274 | rfds = t; | ||||
1275 | |||||
1276 | nl = reallocarray(rfd_names, rn_socket_fds + s->n_fd_store + 1, sizeof(char *)); | ||||
1277 | if (!nl) | ||||
1278 | return -ENOMEM12; | ||||
1279 | |||||
1280 | rfd_names = nl; | ||||
1281 | n_fds = rn_socket_fds; | ||||
1282 | |||||
1283 | LIST_FOREACH(fd_store, fs, s->fd_store)for ((fs) = (s->fd_store); (fs); (fs) = (fs)->fd_store_next ) { | ||||
1284 | rfds[n_fds] = fs->fd; | ||||
1285 | rfd_names[n_fds] = strdup(strempty(fs->fdname)); | ||||
1286 | if (!rfd_names[n_fds]) | ||||
1287 | return -ENOMEM12; | ||||
1288 | |||||
1289 | rn_storage_fds++; | ||||
1290 | n_fds++; | ||||
1291 | } | ||||
1292 | |||||
1293 | rfd_names[n_fds] = NULL((void*)0); | ||||
1294 | } | ||||
1295 | |||||
1296 | *fds = TAKE_PTR(rfds)({ typeof(rfds) _ptr_ = (rfds); (rfds) = ((void*)0); _ptr_; } ); | ||||
1297 | *fd_names = TAKE_PTR(rfd_names)({ typeof(rfd_names) _ptr_ = (rfd_names); (rfd_names) = ((void *)0); _ptr_; }); | ||||
1298 | *n_socket_fds = rn_socket_fds; | ||||
1299 | *n_storage_fds = rn_storage_fds; | ||||
1300 | |||||
1301 | return 0; | ||||
1302 | } | ||||
1303 | |||||
1304 | static int service_allocate_exec_fd_event_source( | ||||
1305 | Service *s, | ||||
1306 | int fd, | ||||
1307 | sd_event_source **ret_event_source) { | ||||
1308 | |||||
1309 | _cleanup_(sd_event_source_unrefp)__attribute__((cleanup(sd_event_source_unrefp))) sd_event_source *source = NULL((void*)0); | ||||
1310 | int r; | ||||
1311 | |||||
1312 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1312, __PRETTY_FUNCTION__ ); } while (0); | ||||
1313 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/core/service.c", 1313 , __PRETTY_FUNCTION__); } while (0); | ||||
1314 | assert(ret_event_source)do { if ((__builtin_expect(!!(!(ret_event_source)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret_event_source"), "../src/core/service.c" , 1314, __PRETTY_FUNCTION__); } while (0); | ||||
1315 | |||||
1316 | r = sd_event_add_io(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->event, &source, fd, 0, service_dispatch_exec_io, s); | ||||
1317 | if (r < 0) | ||||
1318 | return log_unit_error_errno(UNIT(s), r, "Failed to allocate exec_fd event source: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/service.c", 1318, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to allocate exec_fd event source: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/service.c", 1318, __func__, "Failed to allocate exec_fd event source: %m" ); }); | ||||
1319 | |||||
1320 | /* This is a bit lower priority than SIGCHLD, as that carries a lot more interesting failure information */ | ||||
1321 | |||||
1322 | r = sd_event_source_set_priority(source, SD_EVENT_PRIORITY_NORMAL-3); | ||||
1323 | if (r < 0) | ||||
1324 | return log_unit_error_errno(UNIT(s), r, "Failed to adjust priority of exec_fd event source: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/service.c", 1324, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to adjust priority of exec_fd event source: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/service.c", 1324, __func__, "Failed to adjust priority of exec_fd event source: %m" ); }); | ||||
1325 | |||||
1326 | (void) sd_event_source_set_description(source, "service event_fd"); | ||||
1327 | |||||
1328 | r = sd_event_source_set_io_fd_own(source, true1); | ||||
1329 | if (r < 0) | ||||
1330 | return log_unit_error_errno(UNIT(s), r, "Failed to pass ownership of fd to event source: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/service.c", 1330, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to pass ownership of fd to event source: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), r, "../src/core/service.c", 1330, __func__, "Failed to pass ownership of fd to event source: %m" ); }); | ||||
1331 | |||||
1332 | *ret_event_source = TAKE_PTR(source)({ typeof(source) _ptr_ = (source); (source) = ((void*)0); _ptr_ ; }); | ||||
1333 | return 0; | ||||
1334 | } | ||||
1335 | |||||
1336 | static int service_allocate_exec_fd( | ||||
1337 | Service *s, | ||||
1338 | sd_event_source **ret_event_source, | ||||
1339 | int* ret_exec_fd) { | ||||
1340 | |||||
1341 | _cleanup_close_pair___attribute__((cleanup(close_pairp))) int p[2] = { -1, -1 }; | ||||
1342 | int r; | ||||
1343 | |||||
1344 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1344, __PRETTY_FUNCTION__ ); } while (0); | ||||
1345 | assert(ret_event_source)do { if ((__builtin_expect(!!(!(ret_event_source)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret_event_source"), "../src/core/service.c" , 1345, __PRETTY_FUNCTION__); } while (0); | ||||
1346 | assert(ret_exec_fd)do { if ((__builtin_expect(!!(!(ret_exec_fd)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ret_exec_fd"), "../src/core/service.c", 1346, __PRETTY_FUNCTION__); } while (0); | ||||
1347 | |||||
1348 | if (pipe2(p, O_CLOEXEC02000000|O_NONBLOCK04000) < 0) | ||||
1349 | return log_unit_error_errno(UNIT(s), errno, "Failed to allocate exec_fd pipe: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, (*__errno_location ()), "../src/core/service.c", 1349, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "Failed to allocate exec_fd pipe: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), (*__errno_location ()), "../src/core/service.c", 1349, __func__ , "Failed to allocate exec_fd pipe: %m"); }); | ||||
1350 | |||||
1351 | r = service_allocate_exec_fd_event_source(s, p[0], ret_event_source); | ||||
1352 | if (r < 0) | ||||
1353 | return r; | ||||
1354 | |||||
1355 | p[0] = -1; | ||||
1356 | *ret_exec_fd = TAKE_FD(p[1])({ int _fd_ = (p[1]); (p[1]) = -1; _fd_; }); | ||||
1357 | |||||
1358 | return 0; | ||||
1359 | } | ||||
1360 | |||||
1361 | static bool_Bool service_exec_needs_notify_socket(Service *s, ExecFlags flags) { | ||||
1362 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1362, __PRETTY_FUNCTION__ ); } while (0); | ||||
1363 | |||||
1364 | /* Notifications are accepted depending on the process and | ||||
1365 | * the access setting of the service: | ||||
1366 | * process: \ access: NONE MAIN EXEC ALL | ||||
1367 | * main no yes yes yes | ||||
1368 | * control no no yes yes | ||||
1369 | * other (forked) no no no yes */ | ||||
1370 | |||||
1371 | if (flags & EXEC_IS_CONTROL) | ||||
1372 | /* A control process */ | ||||
1373 | return IN_SET(s->notify_access, NOTIFY_EXEC, NOTIFY_ALL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){NOTIFY_EXEC, NOTIFY_ALL})/sizeof(int)]; switch (s->notify_access) { case NOTIFY_EXEC: case NOTIFY_ALL: _found = 1; break; default: break; } _found; }); | ||||
1374 | |||||
1375 | /* We only spawn main processes and control processes, so any | ||||
1376 | * process that is not a control process is a main process */ | ||||
1377 | return s->notify_access != NOTIFY_NONE; | ||||
1378 | } | ||||
1379 | |||||
1380 | static int service_spawn( | ||||
1381 | Service *s, | ||||
1382 | ExecCommand *c, | ||||
1383 | usec_t timeout, | ||||
1384 | ExecFlags flags, | ||||
1385 | pid_t *_pid) { | ||||
1386 | |||||
1387 | ExecParameters exec_params = { | ||||
1388 | .flags = flags, | ||||
1389 | .stdin_fd = -1, | ||||
1390 | .stdout_fd = -1, | ||||
1391 | .stderr_fd = -1, | ||||
1392 | .exec_fd = -1, | ||||
1393 | }; | ||||
1394 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **final_env = NULL((void*)0), **our_env = NULL((void*)0), **fd_names = NULL((void*)0); | ||||
1395 | _cleanup_(sd_event_source_unrefp)__attribute__((cleanup(sd_event_source_unrefp))) sd_event_source *exec_fd_source = NULL((void*)0); | ||||
1396 | size_t n_socket_fds = 0, n_storage_fds = 0, n_env = 0; | ||||
1397 | _cleanup_close___attribute__((cleanup(closep))) int exec_fd = -1; | ||||
1398 | _cleanup_free___attribute__((cleanup(freep))) int *fds = NULL((void*)0); | ||||
1399 | pid_t pid; | ||||
1400 | int r; | ||||
1401 | |||||
1402 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1402, __PRETTY_FUNCTION__ ); } while (0); | ||||
| |||||
1403 | assert(c)do { if ((__builtin_expect(!!(!(c)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("c"), "../src/core/service.c", 1403, __PRETTY_FUNCTION__ ); } while (0); | ||||
1404 | assert(_pid)do { if ((__builtin_expect(!!(!(_pid)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("_pid"), "../src/core/service.c", 1404, __PRETTY_FUNCTION__ ); } while (0); | ||||
1405 | |||||
1406 | r = unit_prepare_exec(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
1407 | if (r < 0) | ||||
1408 | return r; | ||||
1409 | |||||
1410 | if (flags & EXEC_IS_CONTROL) { | ||||
1411 | /* If this is a control process, mask the permissions/chroot application if this is requested. */ | ||||
1412 | if (s->permissions_start_only) | ||||
1413 | exec_params.flags &= ~EXEC_APPLY_SANDBOXING; | ||||
1414 | if (s->root_directory_start_only) | ||||
1415 | exec_params.flags &= ~EXEC_APPLY_CHROOT; | ||||
1416 | } | ||||
1417 | |||||
1418 | if ((flags & EXEC_PASS_FDS) || | ||||
1419 | s->exec_context.std_input == EXEC_INPUT_SOCKET || | ||||
1420 | s->exec_context.std_output == EXEC_OUTPUT_SOCKET || | ||||
1421 | s->exec_context.std_error == EXEC_OUTPUT_SOCKET) { | ||||
1422 | |||||
1423 | r = service_collect_fds(s, &fds, &fd_names, &n_socket_fds, &n_storage_fds); | ||||
1424 | if (r
| ||||
1425 | return r; | ||||
1426 | |||||
1427 | log_unit_debug(UNIT(s), "Passing %zu fds to service", n_socket_fds + n_storage_fds)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 1427, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Passing %zu fds to service", n_socket_fds + n_storage_fds) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 1427, __func__, "Passing %zu fds to service" , n_socket_fds + n_storage_fds); }); | ||||
1428 | } | ||||
1429 | |||||
1430 | if (!FLAGS_SET(flags, EXEC_IS_CONTROL)(((flags) & (EXEC_IS_CONTROL)) == (EXEC_IS_CONTROL)) && s->type == SERVICE_EXEC) { | ||||
1431 | assert(!s->exec_fd_event_source)do { if ((__builtin_expect(!!(!(!s->exec_fd_event_source)) ,0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!s->exec_fd_event_source" ), "../src/core/service.c", 1431, __PRETTY_FUNCTION__); } while (0); | ||||
1432 | |||||
1433 | r = service_allocate_exec_fd(s, &exec_fd_source, &exec_fd); | ||||
1434 | if (r < 0) | ||||
1435 | return r; | ||||
1436 | } | ||||
1437 | |||||
1438 | r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC1), timeout)); | ||||
1439 | if (r < 0) | ||||
1440 | return r; | ||||
| |||||
1441 | |||||
1442 | our_env = new0(char*, 9)((char**) calloc((9), sizeof(char*))); | ||||
1443 | if (!our_env) | ||||
1444 | return -ENOMEM12; | ||||
1445 | |||||
1446 | if (service_exec_needs_notify_socket(s, flags)) | ||||
1447 | if (asprintf(our_env + n_env++, "NOTIFY_SOCKET=%s", UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->notify_socket) < 0) | ||||
1448 | return -ENOMEM12; | ||||
1449 | |||||
1450 | if (s->main_pid > 0) | ||||
1451 | if (asprintf(our_env + n_env++, "MAINPID="PID_FMT"%" "i", s->main_pid) < 0) | ||||
1452 | return -ENOMEM12; | ||||
1453 | |||||
1454 | if (MANAGER_IS_USER(UNIT(s)->manager)((({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager)->unit_file_scope != UNIT_FILE_SYSTEM )) | ||||
1455 | if (asprintf(our_env + n_env++, "MANAGERPID="PID_FMT"%" "i", getpid_cached()) < 0) | ||||
1456 | return -ENOMEM12; | ||||
1457 | |||||
1458 | if (s->socket_fd >= 0) { | ||||
1459 | union sockaddr_union sa; | ||||
1460 | socklen_t salen = sizeof(sa); | ||||
1461 | |||||
1462 | /* If this is a per-connection service instance, let's set $REMOTE_ADDR and $REMOTE_PORT to something | ||||
1463 | * useful. Note that we do this only when we are still connected at this point in time, which we might | ||||
1464 | * very well not be. Hence we ignore all errors when retrieving peer information (as that might result | ||||
1465 | * in ENOTCONN), and just use whate we can use. */ | ||||
1466 | |||||
1467 | if (getpeername(s->socket_fd, &sa.sa, &salen) >= 0 && | ||||
1468 | IN_SET(sa.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){2, 10, 40})/sizeof(int)]; switch(sa.sa.sa_family ) { case 2: case 10: case 40: _found = 1; break; default: break ; } _found; })) { | ||||
1469 | |||||
1470 | _cleanup_free___attribute__((cleanup(freep))) char *addr = NULL((void*)0); | ||||
1471 | char *t; | ||||
1472 | unsigned port; | ||||
1473 | |||||
1474 | r = sockaddr_pretty(&sa.sa, salen, true1, false0, &addr); | ||||
1475 | if (r < 0) | ||||
1476 | return r; | ||||
1477 | |||||
1478 | t = strappend("REMOTE_ADDR=", addr); | ||||
1479 | if (!t) | ||||
1480 | return -ENOMEM12; | ||||
1481 | our_env[n_env++] = t; | ||||
1482 | |||||
1483 | r = sockaddr_port(&sa.sa, &port); | ||||
1484 | if (r < 0) | ||||
1485 | return r; | ||||
1486 | |||||
1487 | if (asprintf(&t, "REMOTE_PORT=%u", port) < 0) | ||||
1488 | return -ENOMEM12; | ||||
1489 | our_env[n_env++] = t; | ||||
1490 | } | ||||
1491 | } | ||||
1492 | |||||
1493 | if (flags & EXEC_SETENV_RESULT) { | ||||
1494 | if (asprintf(our_env + n_env++, "SERVICE_RESULT=%s", service_result_to_string(s->result)) < 0) | ||||
1495 | return -ENOMEM12; | ||||
1496 | |||||
1497 | if (s->main_exec_status.pid > 0 && | ||||
1498 | dual_timestamp_is_set(&s->main_exec_status.exit_timestamp)) { | ||||
1499 | if (asprintf(our_env + n_env++, "EXIT_CODE=%s", sigchld_code_to_string(s->main_exec_status.code)) < 0) | ||||
1500 | return -ENOMEM12; | ||||
1501 | |||||
1502 | if (s->main_exec_status.code == CLD_EXITEDCLD_EXITED) | ||||
1503 | r = asprintf(our_env + n_env++, "EXIT_STATUS=%i", s->main_exec_status.status); | ||||
1504 | else | ||||
1505 | r = asprintf(our_env + n_env++, "EXIT_STATUS=%s", signal_to_string(s->main_exec_status.status)); | ||||
1506 | if (r < 0) | ||||
1507 | return -ENOMEM12; | ||||
1508 | } | ||||
1509 | } | ||||
1510 | |||||
1511 | unit_set_exec_params(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), &exec_params); | ||||
1512 | |||||
1513 | final_env = strv_env_merge(2, exec_params.environment, our_env, NULL((void*)0)); | ||||
1514 | if (!final_env) | ||||
1515 | return -ENOMEM12; | ||||
1516 | |||||
1517 | /* System services should get a new keyring by default. */ | ||||
1518 | SET_FLAG(exec_params.flags, EXEC_NEW_KEYRING, MANAGER_IS_SYSTEM(UNIT(s)->manager))(exec_params.flags) = (((({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager)-> unit_file_scope == UNIT_FILE_SYSTEM)) ? ((exec_params.flags) | (EXEC_NEW_KEYRING)) : ((exec_params.flags) & ~(EXEC_NEW_KEYRING )); | ||||
1519 | |||||
1520 | /* System D-Bus needs nss-systemd disabled, so that we don't deadlock */ | ||||
1521 | SET_FLAG(exec_params.flags, EXEC_NSS_BYPASS_BUS,(exec_params.flags) = (((({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager)-> unit_file_scope == UNIT_FILE_SYSTEM) && unit_has_name (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), "dbus.service")) ? ((exec_params.flags ) | (EXEC_NSS_BYPASS_BUS)) : ((exec_params.flags) & ~(EXEC_NSS_BYPASS_BUS )) | ||||
1522 | MANAGER_IS_SYSTEM(UNIT(s)->manager) && unit_has_name(UNIT(s), SPECIAL_DBUS_SERVICE))(exec_params.flags) = (((({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager)-> unit_file_scope == UNIT_FILE_SYSTEM) && unit_has_name (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), "dbus.service")) ? ((exec_params.flags ) | (EXEC_NSS_BYPASS_BUS)) : ((exec_params.flags) & ~(EXEC_NSS_BYPASS_BUS )); | ||||
1523 | |||||
1524 | exec_params.argv = c->argv; | ||||
1525 | exec_params.environment = final_env; | ||||
1526 | exec_params.fds = fds; | ||||
1527 | exec_params.fd_names = fd_names; | ||||
1528 | exec_params.n_socket_fds = n_socket_fds; | ||||
1529 | exec_params.n_storage_fds = n_storage_fds; | ||||
1530 | exec_params.watchdog_usec = s->watchdog_usec; | ||||
1531 | exec_params.selinux_context_net = s->socket_fd_selinux_context_net; | ||||
1532 | if (s->type == SERVICE_IDLE) | ||||
1533 | exec_params.idle_pipe = UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->idle_pipe; | ||||
1534 | exec_params.stdin_fd = s->stdin_fd; | ||||
1535 | exec_params.stdout_fd = s->stdout_fd; | ||||
1536 | exec_params.stderr_fd = s->stderr_fd; | ||||
1537 | exec_params.exec_fd = exec_fd; | ||||
1538 | |||||
1539 | r = exec_spawn(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), | ||||
1540 | c, | ||||
1541 | &s->exec_context, | ||||
1542 | &exec_params, | ||||
1543 | s->exec_runtime, | ||||
1544 | &s->dynamic_creds, | ||||
1545 | &pid); | ||||
1546 | if (r < 0) | ||||
1547 | return r; | ||||
1548 | |||||
1549 | s->exec_fd_event_source = TAKE_PTR(exec_fd_source)({ typeof(exec_fd_source) _ptr_ = (exec_fd_source); (exec_fd_source ) = ((void*)0); _ptr_; }); | ||||
1550 | s->exec_fd_hot = false0; | ||||
1551 | |||||
1552 | r = unit_watch_pid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), pid, true1); | ||||
1553 | if (r < 0) | ||||
1554 | return r; | ||||
1555 | |||||
1556 | *_pid = pid; | ||||
1557 | |||||
1558 | return 0; | ||||
1559 | } | ||||
1560 | |||||
1561 | static int main_pid_good(Service *s) { | ||||
1562 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1562, __PRETTY_FUNCTION__ ); } while (0); | ||||
1563 | |||||
1564 | /* Returns 0 if the pid is dead, > 0 if it is good, < 0 if we don't know */ | ||||
1565 | |||||
1566 | /* If we know the pid file, then let's just check if it is | ||||
1567 | * still valid */ | ||||
1568 | if (s->main_pid_known) { | ||||
1569 | |||||
1570 | /* If it's an alien child let's check if it is still | ||||
1571 | * alive ... */ | ||||
1572 | if (s->main_pid_alien && s->main_pid > 0) | ||||
1573 | return pid_is_alive(s->main_pid); | ||||
1574 | |||||
1575 | /* .. otherwise assume we'll get a SIGCHLD for it, | ||||
1576 | * which we really should wait for to collect exit | ||||
1577 | * status and code */ | ||||
1578 | return s->main_pid > 0; | ||||
1579 | } | ||||
1580 | |||||
1581 | /* We don't know the pid */ | ||||
1582 | return -EAGAIN11; | ||||
1583 | } | ||||
1584 | |||||
1585 | static int control_pid_good(Service *s) { | ||||
1586 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1586, __PRETTY_FUNCTION__ ); } while (0); | ||||
1587 | |||||
1588 | /* Returns 0 if the control PID is dead, > 0 if it is good. We never actually return < 0 here, but in order to | ||||
1589 | * make this function as similar as possible to main_pid_good() and cgroup_good(), we pretend that < 0 also | ||||
1590 | * means: we can't figure it out. */ | ||||
1591 | |||||
1592 | return s->control_pid > 0; | ||||
1593 | } | ||||
1594 | |||||
1595 | static int cgroup_good(Service *s) { | ||||
1596 | int r; | ||||
1597 | |||||
1598 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1598, __PRETTY_FUNCTION__ ); } while (0); | ||||
1599 | |||||
1600 | /* Returns 0 if the cgroup is empty or doesn't exist, > 0 if it is exists and is populated, < 0 if we can't | ||||
1601 | * figure it out */ | ||||
1602 | |||||
1603 | if (!UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->cgroup_path) | ||||
1604 | return 0; | ||||
1605 | |||||
1606 | r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER"_systemd", UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->cgroup_path); | ||||
1607 | if (r < 0) | ||||
1608 | return r; | ||||
1609 | |||||
1610 | return r == 0; | ||||
1611 | } | ||||
1612 | |||||
1613 | static bool_Bool service_shall_restart(Service *s) { | ||||
1614 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1614, __PRETTY_FUNCTION__ ); } while (0); | ||||
1615 | |||||
1616 | /* Don't restart after manual stops */ | ||||
1617 | if (s->forbid_restart) | ||||
1618 | return false0; | ||||
1619 | |||||
1620 | /* Never restart if this is configured as special exception */ | ||||
1621 | if (exit_status_set_test(&s->restart_prevent_status, s->main_exec_status.code, s->main_exec_status.status)) | ||||
1622 | return false0; | ||||
1623 | |||||
1624 | /* Restart if the exit code/status are configured as restart triggers */ | ||||
1625 | if (exit_status_set_test(&s->restart_force_status, s->main_exec_status.code, s->main_exec_status.status)) | ||||
1626 | return true1; | ||||
1627 | |||||
1628 | switch (s->restart) { | ||||
1629 | |||||
1630 | case SERVICE_RESTART_NO: | ||||
1631 | return false0; | ||||
1632 | |||||
1633 | case SERVICE_RESTART_ALWAYS: | ||||
1634 | return true1; | ||||
1635 | |||||
1636 | case SERVICE_RESTART_ON_SUCCESS: | ||||
1637 | return s->result == SERVICE_SUCCESS; | ||||
1638 | |||||
1639 | case SERVICE_RESTART_ON_FAILURE: | ||||
1640 | return !IN_SET(s->result, SERVICE_SUCCESS, SERVICE_SKIP_CONDITION)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_SUCCESS, SERVICE_SKIP_CONDITION} )/sizeof(int)]; switch(s->result) { case SERVICE_SUCCESS: case SERVICE_SKIP_CONDITION: _found = 1; break; default: break; } _found; }); | ||||
1641 | |||||
1642 | case SERVICE_RESTART_ON_ABNORMAL: | ||||
1643 | return !IN_SET(s->result, SERVICE_SUCCESS, SERVICE_FAILURE_EXIT_CODE, SERVICE_SKIP_CONDITION)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_SUCCESS, SERVICE_FAILURE_EXIT_CODE , SERVICE_SKIP_CONDITION})/sizeof(int)]; switch(s->result) { case SERVICE_SUCCESS: case SERVICE_FAILURE_EXIT_CODE: case SERVICE_SKIP_CONDITION: _found = 1; break; default: break; } _found; }); | ||||
1644 | |||||
1645 | case SERVICE_RESTART_ON_WATCHDOG: | ||||
1646 | return s->result == SERVICE_FAILURE_WATCHDOG; | ||||
1647 | |||||
1648 | case SERVICE_RESTART_ON_ABORT: | ||||
1649 | return IN_SET(s->result, SERVICE_FAILURE_SIGNAL, SERVICE_FAILURE_CORE_DUMP)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_FAILURE_SIGNAL, SERVICE_FAILURE_CORE_DUMP })/sizeof(int)]; switch(s->result) { case SERVICE_FAILURE_SIGNAL : case SERVICE_FAILURE_CORE_DUMP: _found = 1; break; default: break; } _found; }); | ||||
1650 | |||||
1651 | default: | ||||
1652 | assert_not_reached("unknown restart setting")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "unknown restart setting"), "../src/core/service.c", 1652, __PRETTY_FUNCTION__ ); } while (0); | ||||
1653 | } | ||||
1654 | } | ||||
1655 | |||||
1656 | static bool_Bool service_will_restart(Unit *u) { | ||||
1657 | Service *s = SERVICE(u); | ||||
1658 | |||||
1659 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1659, __PRETTY_FUNCTION__ ); } while (0); | ||||
1660 | |||||
1661 | if (s->will_auto_restart) | ||||
1662 | return true1; | ||||
1663 | if (s->state == SERVICE_AUTO_RESTART) | ||||
1664 | return true1; | ||||
1665 | if (!UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->job) | ||||
1666 | return false0; | ||||
1667 | if (UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->job->type == JOB_START) | ||||
1668 | return true1; | ||||
1669 | |||||
1670 | return false0; | ||||
1671 | } | ||||
1672 | |||||
1673 | static void service_enter_dead(Service *s, ServiceResult f, bool_Bool allow_restart) { | ||||
1674 | ServiceState end_state; | ||||
1675 | int r; | ||||
1676 | |||||
1677 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1677, __PRETTY_FUNCTION__ ); } while (0); | ||||
1678 | |||||
1679 | /* If there's a stop job queued before we enter the DEAD state, we shouldn't act on Restart=, in order to not | ||||
1680 | * undo what has already been enqueued. */ | ||||
1681 | if (unit_stop_pending(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))) | ||||
1682 | allow_restart = false0; | ||||
1683 | |||||
1684 | if (s->result == SERVICE_SUCCESS) | ||||
1685 | s->result = f; | ||||
1686 | |||||
1687 | if (s->result == SERVICE_SUCCESS) { | ||||
1688 | unit_log_success(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
1689 | end_state = SERVICE_DEAD; | ||||
1690 | } else if (s->result == SERVICE_SKIP_CONDITION) { | ||||
1691 | unit_log_skip(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), service_result_to_string(s->result)); | ||||
1692 | end_state = SERVICE_DEAD; | ||||
1693 | } else { | ||||
1694 | unit_log_failure(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), service_result_to_string(s->result)); | ||||
1695 | end_state = SERVICE_FAILED; | ||||
1696 | } | ||||
1697 | |||||
1698 | if (allow_restart && service_shall_restart(s)) | ||||
1699 | s->will_auto_restart = true1; | ||||
1700 | |||||
1701 | /* Make sure service_release_resources() doesn't destroy our FD store, while we are changing through | ||||
1702 | * SERVICE_FAILED/SERVICE_DEAD before entering into SERVICE_AUTO_RESTART. */ | ||||
1703 | s->n_keep_fd_store ++; | ||||
1704 | |||||
1705 | service_set_state(s, end_state); | ||||
1706 | |||||
1707 | if (s->will_auto_restart) { | ||||
1708 | s->will_auto_restart = false0; | ||||
1709 | |||||
1710 | r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC1), s->restart_usec)); | ||||
1711 | if (r < 0) { | ||||
1712 | s->n_keep_fd_store--; | ||||
1713 | goto fail; | ||||
1714 | } | ||||
1715 | |||||
1716 | service_set_state(s, SERVICE_AUTO_RESTART); | ||||
1717 | } else | ||||
1718 | /* If we shan't restart, then flush out the restart counter. But don't do that immediately, so that the | ||||
1719 | * user can still introspect the counter. Do so on the next start. */ | ||||
1720 | s->flush_n_restarts = true1; | ||||
1721 | |||||
1722 | /* The new state is in effect, let's decrease the fd store ref counter again. Let's also readd us to the GC | ||||
1723 | * queue, so that the fd store is possibly gc'ed again */ | ||||
1724 | s->n_keep_fd_store--; | ||||
1725 | unit_add_to_gc_queue(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
1726 | |||||
1727 | /* The next restart might not be a manual stop, hence reset the flag indicating manual stops */ | ||||
1728 | s->forbid_restart = false0; | ||||
1729 | |||||
1730 | /* We want fresh tmpdirs in case service is started again immediately */ | ||||
1731 | s->exec_runtime = exec_runtime_unref(s->exec_runtime, true1); | ||||
1732 | |||||
1733 | if (s->exec_context.runtime_directory_preserve_mode == EXEC_PRESERVE_NO || | ||||
1734 | (s->exec_context.runtime_directory_preserve_mode == EXEC_PRESERVE_RESTART && !service_will_restart(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })))) | ||||
1735 | /* Also, remove the runtime directory */ | ||||
1736 | exec_context_destroy_runtime_directory(&s->exec_context, UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->prefix[EXEC_DIRECTORY_RUNTIME]); | ||||
1737 | |||||
1738 | /* Get rid of the IPC bits of the user */ | ||||
1739 | unit_unref_uid_gid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), true1); | ||||
1740 | |||||
1741 | /* Release the user, and destroy it if we are the only remaining owner */ | ||||
1742 | dynamic_creds_destroy(&s->dynamic_creds); | ||||
1743 | |||||
1744 | /* Try to delete the pid file. At this point it will be | ||||
1745 | * out-of-date, and some software might be confused by it, so | ||||
1746 | * let's remove it. */ | ||||
1747 | if (s->pid_file) | ||||
1748 | (void) unlink(s->pid_file); | ||||
1749 | |||||
1750 | return; | ||||
1751 | |||||
1752 | fail: | ||||
1753 | log_unit_warning_errno(UNIT(s), r, "Failed to run install restart timer: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 1753, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to run install restart timer: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 1753, __func__, "Failed to run install restart timer: %m" ); }); | ||||
1754 | service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false0); | ||||
1755 | } | ||||
1756 | |||||
1757 | static void service_enter_stop_post(Service *s, ServiceResult f) { | ||||
1758 | int r; | ||||
1759 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1759, __PRETTY_FUNCTION__ ); } while (0); | ||||
1760 | |||||
1761 | if (s->result == SERVICE_SUCCESS) | ||||
1762 | s->result = f; | ||||
1763 | |||||
1764 | service_unwatch_control_pid(s); | ||||
1765 | |||||
1766 | (void) unit_enqueue_rewatch_pids(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
1767 | |||||
1768 | s->control_command = s->exec_command[SERVICE_EXEC_STOP_POST]; | ||||
1769 | if (s->control_command) { | ||||
1770 | s->control_command_id = SERVICE_EXEC_STOP_POST; | ||||
1771 | |||||
1772 | r = service_spawn(s, | ||||
1773 | s->control_command, | ||||
1774 | s->timeout_stop_usec, | ||||
1775 | EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_IS_CONTROL|EXEC_SETENV_RESULT, | ||||
1776 | &s->control_pid); | ||||
1777 | if (r < 0) | ||||
1778 | goto fail; | ||||
1779 | |||||
1780 | service_set_state(s, SERVICE_STOP_POST); | ||||
1781 | } else | ||||
1782 | service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_SUCCESS); | ||||
1783 | |||||
1784 | return; | ||||
1785 | |||||
1786 | fail: | ||||
1787 | log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop-post' task: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 1787, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to run 'stop-post' task: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 1787, __func__, "Failed to run 'stop-post' task: %m" ); }); | ||||
1788 | service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_RESOURCES); | ||||
1789 | } | ||||
1790 | |||||
1791 | static int state_to_kill_operation(ServiceState state) { | ||||
1792 | switch (state) { | ||||
1793 | |||||
1794 | case SERVICE_STOP_SIGABRT: | ||||
1795 | return KILL_ABORT; | ||||
1796 | |||||
1797 | case SERVICE_STOP_SIGTERM: | ||||
1798 | case SERVICE_FINAL_SIGTERM: | ||||
1799 | return KILL_TERMINATE; | ||||
1800 | |||||
1801 | case SERVICE_STOP_SIGKILL: | ||||
1802 | case SERVICE_FINAL_SIGKILL: | ||||
1803 | return KILL_KILL; | ||||
1804 | |||||
1805 | default: | ||||
1806 | return _KILL_OPERATION_INVALID; | ||||
1807 | } | ||||
1808 | } | ||||
1809 | |||||
1810 | static void service_enter_signal(Service *s, ServiceState state, ServiceResult f) { | ||||
1811 | int r; | ||||
1812 | |||||
1813 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1813, __PRETTY_FUNCTION__ ); } while (0); | ||||
1814 | |||||
1815 | if (s->result == SERVICE_SUCCESS) | ||||
1816 | s->result = f; | ||||
1817 | |||||
1818 | /* Before sending any signal, make sure we track all members of this cgroup */ | ||||
1819 | (void) unit_watch_all_pids(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
1820 | |||||
1821 | /* Also, enqueue a job that we recheck all our PIDs a bit later, given that it's likely some processes have | ||||
1822 | * died now */ | ||||
1823 | (void) unit_enqueue_rewatch_pids(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
1824 | |||||
1825 | r = unit_kill_context( | ||||
1826 | UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), | ||||
1827 | &s->kill_context, | ||||
1828 | state_to_kill_operation(state), | ||||
1829 | s->main_pid, | ||||
1830 | s->control_pid, | ||||
1831 | s->main_pid_alien); | ||||
1832 | if (r < 0) | ||||
1833 | goto fail; | ||||
1834 | |||||
1835 | if (r > 0) { | ||||
1836 | r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC1), s->timeout_stop_usec)); | ||||
1837 | if (r < 0) | ||||
1838 | goto fail; | ||||
1839 | |||||
1840 | service_set_state(s, state); | ||||
1841 | } else if (IN_SET(state, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM })/sizeof(int)]; switch(state) { case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: _found = 1; break; default: break; } _found ; }) && s->kill_context.send_sigkill) | ||||
1842 | service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_SUCCESS); | ||||
1843 | else if (IN_SET(state, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL})/sizeof(int)]; switch(state) { case SERVICE_STOP_SIGABRT : case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: _found = 1; break; default: break; } _found; })) | ||||
1844 | service_enter_stop_post(s, SERVICE_SUCCESS); | ||||
1845 | else if (state == SERVICE_FINAL_SIGTERM && s->kill_context.send_sigkill) | ||||
1846 | service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_SUCCESS); | ||||
1847 | else | ||||
1848 | service_enter_dead(s, SERVICE_SUCCESS, true1); | ||||
1849 | |||||
1850 | return; | ||||
1851 | |||||
1852 | fail: | ||||
1853 | log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 1853, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to kill processes: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 1853, __func__, "Failed to kill processes: %m" ); }); | ||||
1854 | |||||
1855 | if (IN_SET(state, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL})/sizeof(int)]; switch(state) { case SERVICE_STOP_SIGABRT : case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL: _found = 1; break; default: break; } _found; })) | ||||
1856 | service_enter_stop_post(s, SERVICE_FAILURE_RESOURCES); | ||||
1857 | else | ||||
1858 | service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true1); | ||||
1859 | } | ||||
1860 | |||||
1861 | static void service_enter_stop_by_notify(Service *s) { | ||||
1862 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1862, __PRETTY_FUNCTION__ ); } while (0); | ||||
1863 | |||||
1864 | (void) unit_enqueue_rewatch_pids(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
1865 | |||||
1866 | service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC1), s->timeout_stop_usec)); | ||||
1867 | |||||
1868 | /* The service told us it's stopping, so it's as if we SIGTERM'd it. */ | ||||
1869 | service_set_state(s, SERVICE_STOP_SIGTERM); | ||||
1870 | } | ||||
1871 | |||||
1872 | static void service_enter_stop(Service *s, ServiceResult f) { | ||||
1873 | int r; | ||||
1874 | |||||
1875 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1875, __PRETTY_FUNCTION__ ); } while (0); | ||||
1876 | |||||
1877 | if (s->result == SERVICE_SUCCESS) | ||||
1878 | s->result = f; | ||||
1879 | |||||
1880 | service_unwatch_control_pid(s); | ||||
1881 | (void) unit_enqueue_rewatch_pids(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
1882 | |||||
1883 | s->control_command = s->exec_command[SERVICE_EXEC_STOP]; | ||||
1884 | if (s->control_command) { | ||||
1885 | s->control_command_id = SERVICE_EXEC_STOP; | ||||
1886 | |||||
1887 | r = service_spawn(s, | ||||
1888 | s->control_command, | ||||
1889 | s->timeout_stop_usec, | ||||
1890 | EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_SETENV_RESULT, | ||||
1891 | &s->control_pid); | ||||
1892 | if (r < 0) | ||||
1893 | goto fail; | ||||
1894 | |||||
1895 | service_set_state(s, SERVICE_STOP); | ||||
1896 | } else | ||||
1897 | service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_SUCCESS); | ||||
1898 | |||||
1899 | return; | ||||
1900 | |||||
1901 | fail: | ||||
1902 | log_unit_warning_errno(UNIT(s), r, "Failed to run 'stop' task: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 1902, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to run 'stop' task: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 1902, __func__, "Failed to run 'stop' task: %m" ); }); | ||||
1903 | service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES); | ||||
1904 | } | ||||
1905 | |||||
1906 | static bool_Bool service_good(Service *s) { | ||||
1907 | int main_pid_ok; | ||||
1908 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1908, __PRETTY_FUNCTION__ ); } while (0); | ||||
1909 | |||||
1910 | if (s->type == SERVICE_DBUS && !s->bus_name_good) | ||||
1911 | return false0; | ||||
1912 | |||||
1913 | main_pid_ok = main_pid_good(s); | ||||
1914 | if (main_pid_ok > 0) /* It's alive */ | ||||
1915 | return true1; | ||||
1916 | if (main_pid_ok == 0) /* It's dead */ | ||||
1917 | return false0; | ||||
1918 | |||||
1919 | /* OK, we don't know anything about the main PID, maybe | ||||
1920 | * because there is none. Let's check the control group | ||||
1921 | * instead. */ | ||||
1922 | |||||
1923 | return cgroup_good(s) != 0; | ||||
1924 | } | ||||
1925 | |||||
1926 | static void service_enter_running(Service *s, ServiceResult f) { | ||||
1927 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1927, __PRETTY_FUNCTION__ ); } while (0); | ||||
1928 | |||||
1929 | if (s->result == SERVICE_SUCCESS) | ||||
1930 | s->result = f; | ||||
1931 | |||||
1932 | service_unwatch_control_pid(s); | ||||
1933 | |||||
1934 | if (s->result != SERVICE_SUCCESS) | ||||
1935 | service_enter_signal(s, SERVICE_STOP_SIGTERM, f); | ||||
1936 | else if (service_good(s)) { | ||||
1937 | |||||
1938 | /* If there are any queued up sd_notify() notifications, process them now */ | ||||
1939 | if (s->notify_state == NOTIFY_RELOADING) | ||||
1940 | service_enter_reload_by_notify(s); | ||||
1941 | else if (s->notify_state == NOTIFY_STOPPING) | ||||
1942 | service_enter_stop_by_notify(s); | ||||
1943 | else { | ||||
1944 | service_set_state(s, SERVICE_RUNNING); | ||||
1945 | service_arm_timer(s, usec_add(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->active_enter_timestamp.monotonic, s->runtime_max_usec)); | ||||
1946 | } | ||||
1947 | |||||
1948 | } else if (s->remain_after_exit) | ||||
1949 | service_set_state(s, SERVICE_EXITED); | ||||
1950 | else | ||||
1951 | service_enter_stop(s, SERVICE_SUCCESS); | ||||
1952 | } | ||||
1953 | |||||
1954 | static void service_enter_start_post(Service *s) { | ||||
1955 | int r; | ||||
1956 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1956, __PRETTY_FUNCTION__ ); } while (0); | ||||
1957 | |||||
1958 | service_unwatch_control_pid(s); | ||||
1959 | service_reset_watchdog(s); | ||||
1960 | |||||
1961 | s->control_command = s->exec_command[SERVICE_EXEC_START_POST]; | ||||
1962 | if (s->control_command) { | ||||
1963 | s->control_command_id = SERVICE_EXEC_START_POST; | ||||
1964 | |||||
1965 | r = service_spawn(s, | ||||
1966 | s->control_command, | ||||
1967 | s->timeout_start_usec, | ||||
1968 | EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL, | ||||
1969 | &s->control_pid); | ||||
1970 | if (r < 0) | ||||
1971 | goto fail; | ||||
1972 | |||||
1973 | service_set_state(s, SERVICE_START_POST); | ||||
1974 | } else | ||||
1975 | service_enter_running(s, SERVICE_SUCCESS); | ||||
1976 | |||||
1977 | return; | ||||
1978 | |||||
1979 | fail: | ||||
1980 | log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-post' task: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 1980, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to run 'start-post' task: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 1980, __func__, "Failed to run 'start-post' task: %m" ); }); | ||||
1981 | service_enter_stop(s, SERVICE_FAILURE_RESOURCES); | ||||
1982 | } | ||||
1983 | |||||
1984 | static void service_kill_control_process(Service *s) { | ||||
1985 | int r; | ||||
1986 | |||||
1987 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 1987, __PRETTY_FUNCTION__ ); } while (0); | ||||
1988 | |||||
1989 | if (s->control_pid <= 0) | ||||
1990 | return; | ||||
1991 | |||||
1992 | r = kill_and_sigcont(s->control_pid, SIGKILL9); | ||||
1993 | if (r < 0) { | ||||
1994 | _cleanup_free___attribute__((cleanup(freep))) char *comm = NULL((void*)0); | ||||
1995 | |||||
1996 | (void) get_process_comm(s->control_pid, &comm); | ||||
1997 | |||||
1998 | log_unit_debug_errno(UNIT(s), r, "Failed to kill control process " PID_FMT " (%s), ignoring: %m",({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, r, "../src/core/service.c", 1999, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to kill control process " "%" "i" " (%s), ignoring: %m", s->control_pid, strna(comm )) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | (( 7))), r, "../src/core/service.c", 1999, __func__, "Failed to kill control process " "%" "i" " (%s), ignoring: %m", s->control_pid, strna(comm )); }) | ||||
1999 | s->control_pid, strna(comm))({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, r, "../src/core/service.c", 1999, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to kill control process " "%" "i" " (%s), ignoring: %m", s->control_pid, strna(comm )) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | (( 7))), r, "../src/core/service.c", 1999, __func__, "Failed to kill control process " "%" "i" " (%s), ignoring: %m", s->control_pid, strna(comm )); }); | ||||
2000 | } | ||||
2001 | } | ||||
2002 | |||||
2003 | static void service_enter_start(Service *s) { | ||||
2004 | ExecCommand *c; | ||||
2005 | usec_t timeout; | ||||
2006 | pid_t pid; | ||||
2007 | int r; | ||||
2008 | |||||
2009 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2009, __PRETTY_FUNCTION__ ); } while (0); | ||||
2010 | |||||
2011 | service_unwatch_control_pid(s); | ||||
2012 | service_unwatch_main_pid(s); | ||||
2013 | |||||
2014 | unit_warn_leftover_processes(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
2015 | |||||
2016 | if (s->type == SERVICE_FORKING) { | ||||
2017 | s->control_command_id = SERVICE_EXEC_START; | ||||
2018 | c = s->control_command = s->exec_command[SERVICE_EXEC_START]; | ||||
2019 | |||||
2020 | s->main_command = NULL((void*)0); | ||||
2021 | } else { | ||||
2022 | s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; | ||||
2023 | s->control_command = NULL((void*)0); | ||||
2024 | |||||
2025 | c = s->main_command = s->exec_command[SERVICE_EXEC_START]; | ||||
2026 | } | ||||
2027 | |||||
2028 | if (!c) { | ||||
2029 | if (s->type != SERVICE_ONESHOT) { | ||||
2030 | /* There's no command line configured for the main command? Hmm, that is strange. This can only | ||||
2031 | * happen if the configuration changes at runtime. In this case, let's enter a failure | ||||
2032 | * state. */ | ||||
2033 | log_unit_error(UNIT(s), "There's no 'start' task anymore we could start.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/service.c", 2033, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "There's no 'start' task anymore we could start." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), 0, "../src/core/service.c", 2033, __func__, "There's no 'start' task anymore we could start." ); }); | ||||
2034 | r = -ENXIO6; | ||||
2035 | goto fail; | ||||
2036 | } | ||||
2037 | |||||
2038 | service_enter_start_post(s); | ||||
2039 | return; | ||||
2040 | } | ||||
2041 | |||||
2042 | if (IN_SET(s->type, SERVICE_SIMPLE, SERVICE_IDLE)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_SIMPLE, SERVICE_IDLE})/sizeof(int )]; switch(s->type) { case SERVICE_SIMPLE: case SERVICE_IDLE : _found = 1; break; default: break; } _found; })) | ||||
2043 | /* For simple + idle this is the main process. We don't apply any timeout here, but | ||||
2044 | * service_enter_running() will later apply the .runtime_max_usec timeout. */ | ||||
2045 | timeout = USEC_INFINITY((usec_t) -1); | ||||
2046 | else | ||||
2047 | timeout = s->timeout_start_usec; | ||||
2048 | |||||
2049 | r = service_spawn(s, | ||||
2050 | c, | ||||
2051 | timeout, | ||||
2052 | EXEC_PASS_FDS|EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG, | ||||
2053 | &pid); | ||||
2054 | if (r < 0) | ||||
2055 | goto fail; | ||||
2056 | |||||
2057 | if (IN_SET(s->type, SERVICE_SIMPLE, SERVICE_IDLE)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_SIMPLE, SERVICE_IDLE})/sizeof(int )]; switch(s->type) { case SERVICE_SIMPLE: case SERVICE_IDLE : _found = 1; break; default: break; } _found; })) { | ||||
2058 | /* For simple services we immediately start | ||||
2059 | * the START_POST binaries. */ | ||||
2060 | |||||
2061 | service_set_main_pid(s, pid); | ||||
2062 | service_enter_start_post(s); | ||||
2063 | |||||
2064 | } else if (s->type == SERVICE_FORKING) { | ||||
2065 | |||||
2066 | /* For forking services we wait until the start | ||||
2067 | * process exited. */ | ||||
2068 | |||||
2069 | s->control_pid = pid; | ||||
2070 | service_set_state(s, SERVICE_START); | ||||
2071 | |||||
2072 | } else if (IN_SET(s->type, SERVICE_ONESHOT, SERVICE_DBUS, SERVICE_NOTIFY, SERVICE_EXEC)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_ONESHOT, SERVICE_DBUS, SERVICE_NOTIFY , SERVICE_EXEC})/sizeof(int)]; switch(s->type) { case SERVICE_ONESHOT : case SERVICE_DBUS: case SERVICE_NOTIFY: case SERVICE_EXEC: _found = 1; break; default: break; } _found; })) { | ||||
2073 | |||||
2074 | /* For oneshot services we wait until the start process exited, too, but it is our main process. */ | ||||
2075 | |||||
2076 | /* For D-Bus services we know the main pid right away, but wait for the bus name to appear on the | ||||
2077 | * bus. 'notify' and 'exec' services are similar. */ | ||||
2078 | |||||
2079 | service_set_main_pid(s, pid); | ||||
2080 | service_set_state(s, SERVICE_START); | ||||
2081 | } else | ||||
2082 | assert_not_reached("Unknown service type")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Unknown service type"), "../src/core/service.c", 2082, __PRETTY_FUNCTION__ ); } while (0); | ||||
2083 | |||||
2084 | return; | ||||
2085 | |||||
2086 | fail: | ||||
2087 | log_unit_warning_errno(UNIT(s), r, "Failed to run 'start' task: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 2087, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to run 'start' task: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 2087, __func__, "Failed to run 'start' task: %m" ); }); | ||||
2088 | service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES); | ||||
2089 | } | ||||
2090 | |||||
2091 | static void service_enter_start_pre(Service *s) { | ||||
2092 | int r; | ||||
2093 | |||||
2094 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2094, __PRETTY_FUNCTION__ ); } while (0); | ||||
2095 | |||||
2096 | service_unwatch_control_pid(s); | ||||
2097 | |||||
2098 | s->control_command = s->exec_command[SERVICE_EXEC_START_PRE]; | ||||
2099 | if (s->control_command) { | ||||
2100 | |||||
2101 | unit_warn_leftover_processes(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
2102 | |||||
2103 | s->control_command_id = SERVICE_EXEC_START_PRE; | ||||
2104 | |||||
2105 | r = service_spawn(s, | ||||
2106 | s->control_command, | ||||
2107 | s->timeout_start_usec, | ||||
2108 | EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN, | ||||
2109 | &s->control_pid); | ||||
2110 | if (r < 0) | ||||
2111 | goto fail; | ||||
2112 | |||||
2113 | service_set_state(s, SERVICE_START_PRE); | ||||
2114 | } else | ||||
2115 | service_enter_start(s); | ||||
2116 | |||||
2117 | return; | ||||
2118 | |||||
2119 | fail: | ||||
2120 | log_unit_warning_errno(UNIT(s), r, "Failed to run 'start-pre' task: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 2120, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to run 'start-pre' task: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 2120, __func__, "Failed to run 'start-pre' task: %m" ); }); | ||||
2121 | service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true1); | ||||
2122 | } | ||||
2123 | |||||
2124 | static void service_enter_condition(Service *s) { | ||||
2125 | int r; | ||||
2126 | |||||
2127 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2127, __PRETTY_FUNCTION__ ); } while (0); | ||||
2128 | |||||
2129 | service_unwatch_control_pid(s); | ||||
2130 | |||||
2131 | s->control_command = s->exec_command[SERVICE_EXEC_CONDITION]; | ||||
2132 | if (s->control_command) { | ||||
2133 | |||||
2134 | unit_warn_leftover_processes(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
2135 | |||||
2136 | s->control_command_id = SERVICE_EXEC_CONDITION; | ||||
2137 | |||||
2138 | r = service_spawn(s, | ||||
2139 | s->control_command, | ||||
2140 | s->timeout_start_usec, | ||||
2141 | EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN, | ||||
2142 | &s->control_pid); | ||||
2143 | |||||
2144 | if (r < 0) | ||||
2145 | goto fail; | ||||
2146 | |||||
2147 | service_set_state(s, SERVICE_CONDITION); | ||||
2148 | } else | ||||
2149 | service_enter_start_pre(s); | ||||
2150 | |||||
2151 | return; | ||||
2152 | |||||
2153 | fail: | ||||
2154 | log_unit_warning_errno(UNIT(s), r, "Failed to run 'exec-condition' task: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 2154, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to run 'exec-condition' task: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 2154, __func__, "Failed to run 'exec-condition' task: %m" ); }); | ||||
2155 | service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true1); | ||||
2156 | } | ||||
2157 | |||||
2158 | static void service_enter_restart(Service *s) { | ||||
2159 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | ||||
2160 | int r; | ||||
2161 | |||||
2162 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2162, __PRETTY_FUNCTION__ ); } while (0); | ||||
2163 | |||||
2164 | if (UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->job && UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->job->type == JOB_STOP) { | ||||
2165 | /* Don't restart things if we are going down anyway */ | ||||
2166 | log_unit_info(UNIT(s), "Stop job pending for unit, delaying automatic restart.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (6, 0, "../src/core/service.c", 2166, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Stop job pending for unit, delaying automatic restart." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((6 ))), 0, "../src/core/service.c", 2166, __func__, "Stop job pending for unit, delaying automatic restart." ); }); | ||||
2167 | |||||
2168 | r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC1), s->restart_usec)); | ||||
2169 | if (r < 0) | ||||
2170 | goto fail; | ||||
2171 | |||||
2172 | return; | ||||
2173 | } | ||||
2174 | |||||
2175 | /* Any units that are bound to this service must also be | ||||
2176 | * restarted. We use JOB_RESTART (instead of the more obvious | ||||
2177 | * JOB_START) here so that those dependency jobs will be added | ||||
2178 | * as well. */ | ||||
2179 | r = manager_add_job(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager, JOB_RESTART, UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), JOB_REPLACE, NULL((void*)0), &error, NULL((void*)0)); | ||||
2180 | if (r < 0) | ||||
2181 | goto fail; | ||||
2182 | |||||
2183 | /* Count the jobs we enqueue for restarting. This counter is maintained as long as the unit isn't fully | ||||
2184 | * stopped, i.e. as long as it remains up or remains in auto-start states. The use can reset the counter | ||||
2185 | * explicitly however via the usual "systemctl reset-failure" logic. */ | ||||
2186 | s->n_restarts ++; | ||||
2187 | s->flush_n_restarts = false0; | ||||
2188 | |||||
2189 | log_struct(LOG_INFO,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0 , "../src/core/service.c", 2194, __func__, "MESSAGE_ID=" "5e" "b0" "34" "94" "b6" "58" "48" "70" "a5" "36" "b3" "37" "29" "08" "09" "b3", (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &( _u_)->meta : ((void*)0); _w_; }))->manager->unit_log_format_string , (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->id, (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))-> manager->invocation_log_format_string, (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_ ; }))->invocation_id_string, "MESSAGE=%s: " "Scheduled restart job, restart counter is at %u." , (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->id, s->n_restarts, "N_RESTARTS=%u" , s->n_restarts, ((void*)0)) | ||||
2190 | "MESSAGE_ID=" SD_MESSAGE_UNIT_RESTART_SCHEDULED_STR,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0 , "../src/core/service.c", 2194, __func__, "MESSAGE_ID=" "5e" "b0" "34" "94" "b6" "58" "48" "70" "a5" "36" "b3" "37" "29" "08" "09" "b3", (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &( _u_)->meta : ((void*)0); _w_; }))->manager->unit_log_format_string , (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->id, (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))-> manager->invocation_log_format_string, (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_ ; }))->invocation_id_string, "MESSAGE=%s: " "Scheduled restart job, restart counter is at %u." , (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->id, s->n_restarts, "N_RESTARTS=%u" , s->n_restarts, ((void*)0)) | ||||
2191 | LOG_UNIT_ID(UNIT(s)),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0 , "../src/core/service.c", 2194, __func__, "MESSAGE_ID=" "5e" "b0" "34" "94" "b6" "58" "48" "70" "a5" "36" "b3" "37" "29" "08" "09" "b3", (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &( _u_)->meta : ((void*)0); _w_; }))->manager->unit_log_format_string , (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->id, (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))-> manager->invocation_log_format_string, (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_ ; }))->invocation_id_string, "MESSAGE=%s: " "Scheduled restart job, restart counter is at %u." , (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->id, s->n_restarts, "N_RESTARTS=%u" , s->n_restarts, ((void*)0)) | ||||
2192 | LOG_UNIT_INVOCATION_ID(UNIT(s)),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0 , "../src/core/service.c", 2194, __func__, "MESSAGE_ID=" "5e" "b0" "34" "94" "b6" "58" "48" "70" "a5" "36" "b3" "37" "29" "08" "09" "b3", (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &( _u_)->meta : ((void*)0); _w_; }))->manager->unit_log_format_string , (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->id, (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))-> manager->invocation_log_format_string, (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_ ; }))->invocation_id_string, "MESSAGE=%s: " "Scheduled restart job, restart counter is at %u." , (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->id, s->n_restarts, "N_RESTARTS=%u" , s->n_restarts, ((void*)0)) | ||||
2193 | LOG_UNIT_MESSAGE(UNIT(s), "Scheduled restart job, restart counter is at %u.", s->n_restarts),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0 , "../src/core/service.c", 2194, __func__, "MESSAGE_ID=" "5e" "b0" "34" "94" "b6" "58" "48" "70" "a5" "36" "b3" "37" "29" "08" "09" "b3", (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &( _u_)->meta : ((void*)0); _w_; }))->manager->unit_log_format_string , (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->id, (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))-> manager->invocation_log_format_string, (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_ ; }))->invocation_id_string, "MESSAGE=%s: " "Scheduled restart job, restart counter is at %u." , (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->id, s->n_restarts, "N_RESTARTS=%u" , s->n_restarts, ((void*)0)) | ||||
2194 | "N_RESTARTS=%u", s->n_restarts)log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (6)), 0 , "../src/core/service.c", 2194, __func__, "MESSAGE_ID=" "5e" "b0" "34" "94" "b6" "58" "48" "70" "a5" "36" "b3" "37" "29" "08" "09" "b3", (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &( _u_)->meta : ((void*)0); _w_; }))->manager->unit_log_format_string , (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->id, (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))-> manager->invocation_log_format_string, (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_ ; }))->invocation_id_string, "MESSAGE=%s: " "Scheduled restart job, restart counter is at %u." , (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }))->id, s->n_restarts, "N_RESTARTS=%u" , s->n_restarts, ((void*)0)); | ||||
2195 | |||||
2196 | /* Notify clients about changed restart counter */ | ||||
2197 | unit_add_to_dbus_queue(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); | ||||
2198 | |||||
2199 | /* Note that we stay in the SERVICE_AUTO_RESTART state here, | ||||
2200 | * it will be canceled as part of the service_stop() call that | ||||
2201 | * is executed as part of JOB_RESTART. */ | ||||
2202 | |||||
2203 | return; | ||||
2204 | |||||
2205 | fail: | ||||
2206 | log_unit_warning(UNIT(s), "Failed to schedule restart job: %s", bus_error_message(&error, -r))({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 2206, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to schedule restart job: %s" , bus_error_message(&error, -r)) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), 0, "../src/core/service.c", 2206, __func__ , "Failed to schedule restart job: %s", bus_error_message(& error, -r)); }); | ||||
2207 | service_enter_dead(s, SERVICE_FAILURE_RESOURCES, false0); | ||||
2208 | } | ||||
2209 | |||||
2210 | static void service_enter_reload_by_notify(Service *s) { | ||||
2211 | _cleanup_(sd_bus_error_free)__attribute__((cleanup(sd_bus_error_free))) sd_bus_error error = SD_BUS_ERROR_NULL((const sd_bus_error) {(((void*)0)), (((void*)0)), 0}); | ||||
2212 | int r; | ||||
2213 | |||||
2214 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2214, __PRETTY_FUNCTION__ ); } while (0); | ||||
2215 | |||||
2216 | service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC1), s->timeout_start_usec)); | ||||
2217 | service_set_state(s, SERVICE_RELOAD); | ||||
2218 | |||||
2219 | /* service_enter_reload_by_notify is never called during a reload, thus no loops are possible. */ | ||||
2220 | r = manager_propagate_reload(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager, UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), JOB_FAIL, &error); | ||||
2221 | if (r < 0) | ||||
2222 | log_unit_warning(UNIT(s), "Failed to schedule propagation of reload: %s", bus_error_message(&error, -r))({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 2222, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to schedule propagation of reload: %s" , bus_error_message(&error, -r)) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), 0, "../src/core/service.c", 2222, __func__ , "Failed to schedule propagation of reload: %s", bus_error_message (&error, -r)); }); | ||||
2223 | } | ||||
2224 | |||||
2225 | static void service_enter_reload(Service *s) { | ||||
2226 | int r; | ||||
2227 | |||||
2228 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2228, __PRETTY_FUNCTION__ ); } while (0); | ||||
2229 | |||||
2230 | service_unwatch_control_pid(s); | ||||
2231 | s->reload_result = SERVICE_SUCCESS; | ||||
2232 | |||||
2233 | s->control_command = s->exec_command[SERVICE_EXEC_RELOAD]; | ||||
2234 | if (s->control_command) { | ||||
2235 | s->control_command_id = SERVICE_EXEC_RELOAD; | ||||
2236 | |||||
2237 | r = service_spawn(s, | ||||
2238 | s->control_command, | ||||
2239 | s->timeout_start_usec, | ||||
2240 | EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL, | ||||
2241 | &s->control_pid); | ||||
2242 | if (r < 0) | ||||
2243 | goto fail; | ||||
2244 | |||||
2245 | service_set_state(s, SERVICE_RELOAD); | ||||
2246 | } else | ||||
2247 | service_enter_running(s, SERVICE_SUCCESS); | ||||
2248 | |||||
2249 | return; | ||||
2250 | |||||
2251 | fail: | ||||
2252 | log_unit_warning_errno(UNIT(s), r, "Failed to run 'reload' task: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 2252, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to run 'reload' task: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 2252, __func__, "Failed to run 'reload' task: %m" ); }); | ||||
2253 | s->reload_result = SERVICE_FAILURE_RESOURCES; | ||||
2254 | service_enter_running(s, SERVICE_SUCCESS); | ||||
2255 | } | ||||
2256 | |||||
2257 | static void service_run_next_control(Service *s) { | ||||
2258 | usec_t timeout; | ||||
2259 | int r; | ||||
2260 | |||||
2261 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2261, __PRETTY_FUNCTION__ ); } while (0); | ||||
2262 | assert(s->control_command)do { if ((__builtin_expect(!!(!(s->control_command)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s->control_command"), "../src/core/service.c" , 2262, __PRETTY_FUNCTION__); } while (0); | ||||
2263 | assert(s->control_command->command_next)do { if ((__builtin_expect(!!(!(s->control_command->command_next )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->control_command->command_next" ), "../src/core/service.c", 2263, __PRETTY_FUNCTION__); } while (0); | ||||
2264 | |||||
2265 | assert(s->control_command_id != SERVICE_EXEC_START)do { if ((__builtin_expect(!!(!(s->control_command_id != SERVICE_EXEC_START )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->control_command_id != SERVICE_EXEC_START" ), "../src/core/service.c", 2265, __PRETTY_FUNCTION__); } while (0); | ||||
2266 | |||||
2267 | s->control_command = s->control_command->command_next; | ||||
2268 | service_unwatch_control_pid(s); | ||||
2269 | |||||
2270 | if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD})/sizeof (int)]; switch(s->state) { case SERVICE_CONDITION: case SERVICE_START_PRE : case SERVICE_START: case SERVICE_START_POST: case SERVICE_RUNNING : case SERVICE_RELOAD: _found = 1; break; default: break; } _found ; })) | ||||
2271 | timeout = s->timeout_start_usec; | ||||
2272 | else | ||||
2273 | timeout = s->timeout_stop_usec; | ||||
2274 | |||||
2275 | r = service_spawn(s, | ||||
2276 | s->control_command, | ||||
2277 | timeout, | ||||
2278 | EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL| | ||||
2279 | (IN_SET(s->control_command_id, SERVICE_EXEC_CONDITION, SERVICE_EXEC_START_PRE, SERVICE_EXEC_STOP_POST)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_EXEC_CONDITION, SERVICE_EXEC_START_PRE , SERVICE_EXEC_STOP_POST})/sizeof(int)]; switch(s->control_command_id ) { case SERVICE_EXEC_CONDITION: case SERVICE_EXEC_START_PRE: case SERVICE_EXEC_STOP_POST: _found = 1; break; default: break ; } _found; }) ? EXEC_APPLY_TTY_STDIN : 0)| | ||||
2280 | (IN_SET(s->control_command_id, SERVICE_EXEC_STOP, SERVICE_EXEC_STOP_POST)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_EXEC_STOP, SERVICE_EXEC_STOP_POST })/sizeof(int)]; switch(s->control_command_id) { case SERVICE_EXEC_STOP : case SERVICE_EXEC_STOP_POST: _found = 1; break; default: break ; } _found; }) ? EXEC_SETENV_RESULT : 0), | ||||
2281 | &s->control_pid); | ||||
2282 | if (r < 0) | ||||
2283 | goto fail; | ||||
2284 | |||||
2285 | return; | ||||
2286 | |||||
2287 | fail: | ||||
2288 | log_unit_warning_errno(UNIT(s), r, "Failed to run next control task: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 2288, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to run next control task: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 2288, __func__, "Failed to run next control task: %m" ); }); | ||||
2289 | |||||
2290 | if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START_POST, SERVICE_STOP)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START_POST , SERVICE_STOP})/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START_POST: case SERVICE_STOP : _found = 1; break; default: break; } _found; })) | ||||
2291 | service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES); | ||||
2292 | else if (s->state == SERVICE_STOP_POST) | ||||
2293 | service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true1); | ||||
2294 | else if (s->state == SERVICE_RELOAD) { | ||||
2295 | s->reload_result = SERVICE_FAILURE_RESOURCES; | ||||
2296 | service_enter_running(s, SERVICE_SUCCESS); | ||||
2297 | } else | ||||
2298 | service_enter_stop(s, SERVICE_FAILURE_RESOURCES); | ||||
2299 | } | ||||
2300 | |||||
2301 | static void service_run_next_main(Service *s) { | ||||
2302 | pid_t pid; | ||||
2303 | int r; | ||||
2304 | |||||
2305 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2305, __PRETTY_FUNCTION__ ); } while (0); | ||||
2306 | assert(s->main_command)do { if ((__builtin_expect(!!(!(s->main_command)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s->main_command"), "../src/core/service.c" , 2306, __PRETTY_FUNCTION__); } while (0); | ||||
2307 | assert(s->main_command->command_next)do { if ((__builtin_expect(!!(!(s->main_command->command_next )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->main_command->command_next" ), "../src/core/service.c", 2307, __PRETTY_FUNCTION__); } while (0); | ||||
2308 | assert(s->type == SERVICE_ONESHOT)do { if ((__builtin_expect(!!(!(s->type == SERVICE_ONESHOT )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->type == SERVICE_ONESHOT" ), "../src/core/service.c", 2308, __PRETTY_FUNCTION__); } while (0); | ||||
2309 | |||||
2310 | s->main_command = s->main_command->command_next; | ||||
2311 | service_unwatch_main_pid(s); | ||||
2312 | |||||
2313 | r = service_spawn(s, | ||||
2314 | s->main_command, | ||||
2315 | s->timeout_start_usec, | ||||
2316 | EXEC_PASS_FDS|EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG, | ||||
2317 | &pid); | ||||
2318 | if (r < 0) | ||||
2319 | goto fail; | ||||
2320 | |||||
2321 | service_set_main_pid(s, pid); | ||||
2322 | |||||
2323 | return; | ||||
2324 | |||||
2325 | fail: | ||||
2326 | log_unit_warning_errno(UNIT(s), r, "Failed to run next main task: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, r, "../src/core/service.c", 2326, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to run next main task: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), r, "../src/core/service.c", 2326, __func__, "Failed to run next main task: %m" ); }); | ||||
2327 | service_enter_stop(s, SERVICE_FAILURE_RESOURCES); | ||||
2328 | } | ||||
2329 | |||||
2330 | static int service_start(Unit *u) { | ||||
2331 | Service *s = SERVICE(u); | ||||
2332 | int r; | ||||
2333 | |||||
2334 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2334, __PRETTY_FUNCTION__ ); } while (0); | ||||
2335 | |||||
2336 | /* We cannot fulfill this request right now, try again later | ||||
2337 | * please! */ | ||||
2338 | if (IN_SET(s->state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
2339 | SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
2340 | SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; })) | ||||
2341 | return -EAGAIN11; | ||||
2342 | |||||
2343 | /* Already on it! */ | ||||
2344 | if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST})/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION: case SERVICE_START_PRE: case SERVICE_START : case SERVICE_START_POST: _found = 1; break; default: break; } _found; })) | ||||
2345 | return 0; | ||||
2346 | |||||
2347 | /* A service that will be restarted must be stopped first to | ||||
2348 | * trigger BindsTo and/or OnFailure dependencies. If a user | ||||
2349 | * does not want to wait for the holdoff time to elapse, the | ||||
2350 | * service should be manually restarted, not started. We | ||||
2351 | * simply return EAGAIN here, so that any start jobs stay | ||||
2352 | * queued, and assume that the auto restart timer will | ||||
2353 | * eventually trigger the restart. */ | ||||
2354 | if (s->state == SERVICE_AUTO_RESTART) | ||||
2355 | return -EAGAIN11; | ||||
2356 | |||||
2357 | assert(IN_SET(s->state, SERVICE_DEAD, SERVICE_FAILED))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){SERVICE_DEAD, SERVICE_FAILED})/sizeof(int)] ; switch(s->state) { case SERVICE_DEAD: case SERVICE_FAILED : _found = 1; break; default: break; } _found; }))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("IN_SET(s->state, SERVICE_DEAD, SERVICE_FAILED)" ), "../src/core/service.c", 2357, __PRETTY_FUNCTION__); } while (0); | ||||
2358 | |||||
2359 | /* Make sure we don't enter a busy loop of some kind. */ | ||||
2360 | r = unit_start_limit_test(u); | ||||
2361 | if (r < 0) { | ||||
2362 | service_enter_dead(s, SERVICE_FAILURE_START_LIMIT_HIT, false0); | ||||
2363 | return r; | ||||
2364 | } | ||||
2365 | |||||
2366 | r = unit_acquire_invocation_id(u); | ||||
2367 | if (r < 0) | ||||
2368 | return r; | ||||
2369 | |||||
2370 | s->result = SERVICE_SUCCESS; | ||||
2371 | s->reload_result = SERVICE_SUCCESS; | ||||
2372 | s->main_pid_known = false0; | ||||
2373 | s->main_pid_alien = false0; | ||||
2374 | s->forbid_restart = false0; | ||||
2375 | |||||
2376 | u->reset_accounting = true1; | ||||
2377 | |||||
2378 | s->status_text = mfree(s->status_text); | ||||
2379 | s->status_errno = 0; | ||||
2380 | |||||
2381 | s->notify_state = NOTIFY_UNKNOWN; | ||||
2382 | |||||
2383 | s->watchdog_override_enable = false0; | ||||
2384 | s->watchdog_override_usec = 0; | ||||
2385 | |||||
2386 | /* This is not an automatic restart? Flush the restart counter then */ | ||||
2387 | if (s->flush_n_restarts) { | ||||
2388 | s->n_restarts = 0; | ||||
2389 | s->flush_n_restarts = false0; | ||||
2390 | } | ||||
2391 | |||||
2392 | u->reset_accounting = true1; | ||||
2393 | |||||
2394 | service_enter_condition(s); | ||||
2395 | return 1; | ||||
2396 | } | ||||
2397 | |||||
2398 | static int service_stop(Unit *u) { | ||||
2399 | Service *s = SERVICE(u); | ||||
2400 | |||||
2401 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2401, __PRETTY_FUNCTION__ ); } while (0); | ||||
2402 | |||||
2403 | /* Don't create restart jobs from manual stops. */ | ||||
2404 | s->forbid_restart = true1; | ||||
2405 | |||||
2406 | /* Already on it */ | ||||
2407 | if (IN_SET(s->state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
2408 | SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; }) | ||||
2409 | SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_STOP, SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM , SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM , SERVICE_FINAL_SIGKILL})/sizeof(int)]; switch(s->state) { case SERVICE_STOP: case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM : case SERVICE_STOP_SIGKILL: case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM : case SERVICE_FINAL_SIGKILL: _found = 1; break; default: break ; } _found; })) | ||||
2410 | return 0; | ||||
2411 | |||||
2412 | /* A restart will be scheduled or is in progress. */ | ||||
2413 | if (s->state == SERVICE_AUTO_RESTART) { | ||||
2414 | service_set_state(s, SERVICE_DEAD); | ||||
2415 | return 0; | ||||
2416 | } | ||||
2417 | |||||
2418 | /* If there's already something running we go directly into | ||||
2419 | * kill mode. */ | ||||
2420 | if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RELOAD})/sizeof(int)]; switch(s ->state) { case SERVICE_CONDITION: case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST: case SERVICE_RELOAD : _found = 1; break; default: break; } _found; })) { | ||||
2421 | service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_SUCCESS); | ||||
2422 | return 0; | ||||
2423 | } | ||||
2424 | |||||
2425 | assert(IN_SET(s->state, SERVICE_RUNNING, SERVICE_EXITED))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){SERVICE_RUNNING, SERVICE_EXITED})/sizeof(int )]; switch(s->state) { case SERVICE_RUNNING: case SERVICE_EXITED : _found = 1; break; default: break; } _found; }))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("IN_SET(s->state, SERVICE_RUNNING, SERVICE_EXITED)" ), "../src/core/service.c", 2425, __PRETTY_FUNCTION__); } while (0); | ||||
2426 | |||||
2427 | service_enter_stop(s, SERVICE_SUCCESS); | ||||
2428 | return 1; | ||||
2429 | } | ||||
2430 | |||||
2431 | static int service_reload(Unit *u) { | ||||
2432 | Service *s = SERVICE(u); | ||||
2433 | |||||
2434 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2434, __PRETTY_FUNCTION__ ); } while (0); | ||||
2435 | |||||
2436 | assert(IN_SET(s->state, SERVICE_RUNNING, SERVICE_EXITED))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){SERVICE_RUNNING, SERVICE_EXITED})/sizeof(int )]; switch(s->state) { case SERVICE_RUNNING: case SERVICE_EXITED : _found = 1; break; default: break; } _found; }))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("IN_SET(s->state, SERVICE_RUNNING, SERVICE_EXITED)" ), "../src/core/service.c", 2436, __PRETTY_FUNCTION__); } while (0); | ||||
2437 | |||||
2438 | service_enter_reload(s); | ||||
2439 | return 1; | ||||
2440 | } | ||||
2441 | |||||
2442 | _pure___attribute__ ((pure)) static bool_Bool service_can_reload(Unit *u) { | ||||
2443 | Service *s = SERVICE(u); | ||||
2444 | |||||
2445 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2445, __PRETTY_FUNCTION__ ); } while (0); | ||||
2446 | |||||
2447 | return !!s->exec_command[SERVICE_EXEC_RELOAD]; | ||||
2448 | } | ||||
2449 | |||||
2450 | static unsigned service_exec_command_index(Unit *u, ServiceExecCommand id, ExecCommand *current) { | ||||
2451 | Service *s = SERVICE(u); | ||||
2452 | unsigned idx = 0; | ||||
2453 | ExecCommand *first, *c; | ||||
2454 | |||||
2455 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2455, __PRETTY_FUNCTION__ ); } while (0); | ||||
2456 | |||||
2457 | first = s->exec_command[id]; | ||||
2458 | |||||
2459 | /* Figure out where we are in the list by walking back to the beginning */ | ||||
2460 | for (c = current; c != first; c = c->command_prev) | ||||
2461 | idx++; | ||||
2462 | |||||
2463 | return idx; | ||||
2464 | } | ||||
2465 | |||||
2466 | static int service_serialize_exec_command(Unit *u, FILE *f, ExecCommand *command) { | ||||
2467 | Service *s = SERVICE(u); | ||||
2468 | ServiceExecCommand id; | ||||
2469 | unsigned idx; | ||||
2470 | const char *type; | ||||
2471 | char **arg; | ||||
2472 | _cleanup_free___attribute__((cleanup(freep))) char *args = NULL((void*)0), *p = NULL((void*)0); | ||||
2473 | size_t allocated = 0, length = 0; | ||||
2474 | |||||
2475 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2475, __PRETTY_FUNCTION__ ); } while (0); | ||||
2476 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/core/service.c", 2476, __PRETTY_FUNCTION__ ); } while (0); | ||||
2477 | |||||
2478 | if (!command) | ||||
2479 | return 0; | ||||
2480 | |||||
2481 | if (command == s->control_command) { | ||||
2482 | type = "control"; | ||||
2483 | id = s->control_command_id; | ||||
2484 | } else { | ||||
2485 | type = "main"; | ||||
2486 | id = SERVICE_EXEC_START; | ||||
2487 | } | ||||
2488 | |||||
2489 | idx = service_exec_command_index(u, id, command); | ||||
2490 | |||||
2491 | STRV_FOREACH(arg, command->argv)for ((arg) = (command->argv); (arg) && *(arg); (arg )++) { | ||||
2492 | size_t n; | ||||
2493 | _cleanup_free___attribute__((cleanup(freep))) char *e = NULL((void*)0); | ||||
2494 | |||||
2495 | e = xescape(*arg, WHITESPACE" \t\n\r"); | ||||
2496 | if (!e) | ||||
2497 | return -ENOMEM12; | ||||
2498 | |||||
2499 | n = strlen(e); | ||||
2500 | if (!GREEDY_REALLOC(args, allocated, length + 1 + n + 1)greedy_realloc((void**) &(args), &(allocated), (length + 1 + n + 1), sizeof((args)[0]))) | ||||
2501 | return -ENOMEM12; | ||||
2502 | |||||
2503 | if (length > 0) | ||||
2504 | args[length++] = ' '; | ||||
2505 | |||||
2506 | memcpy(args + length, e, n); | ||||
2507 | length += n; | ||||
2508 | } | ||||
2509 | |||||
2510 | if (!GREEDY_REALLOC(args, allocated, length + 1)greedy_realloc((void**) &(args), &(allocated), (length + 1), sizeof((args)[0]))) | ||||
2511 | return -ENOMEM12; | ||||
2512 | args[length++] = 0; | ||||
2513 | |||||
2514 | p = xescape(command->path, WHITESPACE" \t\n\r"); | ||||
2515 | if (!p) | ||||
2516 | return -ENOMEM12; | ||||
2517 | |||||
2518 | fprintf(f, "%s-command=%s %u %s %s\n", type, service_exec_command_to_string(id), idx, p, args); | ||||
2519 | |||||
2520 | return 0; | ||||
2521 | } | ||||
2522 | |||||
2523 | static int service_serialize(Unit *u, FILE *f, FDSet *fds) { | ||||
2524 | Service *s = SERVICE(u); | ||||
2525 | ServiceFDStore *fs; | ||||
2526 | int r; | ||||
2527 | |||||
2528 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/service.c", 2528, __PRETTY_FUNCTION__ ); } while (0); | ||||
2529 | assert(f)do { if ((__builtin_expect(!!(!(f)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("f"), "../src/core/service.c", 2529, __PRETTY_FUNCTION__ ); } while (0); | ||||
2530 | assert(fds)do { if ((__builtin_expect(!!(!(fds)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fds"), "../src/core/service.c", 2530, __PRETTY_FUNCTION__ ); } while (0); | ||||
2531 | |||||
2532 | unit_serialize_item(u, f, "state", service_state_to_string(s->state)); | ||||
2533 | unit_serialize_item(u, f, "result", service_result_to_string(s->result)); | ||||
2534 | unit_serialize_item(u, f, "reload-result", service_result_to_string(s->reload_result)); | ||||
2535 | |||||
2536 | if (s->control_pid > 0) | ||||
2537 | unit_serialize_item_format(u, f, "control-pid", PID_FMT"%" "i", s->control_pid); | ||||
2538 | |||||
2539 | if (s->main_pid_known && s->main_pid > 0) | ||||
2540 | unit_serialize_item_format(u, f, "main-pid", PID_FMT"%" "i", s->main_pid); | ||||
2541 | |||||
2542 | unit_serialize_item(u, f, "main-pid-known", yes_no(s->main_pid_known)); | ||||
2543 | unit_serialize_item(u, f, "bus-name-good", yes_no(s->bus_name_good)); | ||||
2544 | unit_serialize_item(u, f, "bus-name-owner", s->bus_name_owner); | ||||
2545 | |||||
2546 | unit_serialize_item_format(u, f, "n-restarts", "%u", s->n_restarts); | ||||
2547 | unit_serialize_item(u, f, "flush-n-restarts", yes_no(s->flush_n_restarts)); | ||||
2548 | |||||
2549 | r = unit_serialize_item_escaped(u, f, "status-text", s->status_text); | ||||
2550 | if (r < 0) | ||||
2551 | return r; | ||||
2552 | |||||
2553 | service_serialize_exec_command(u, f, s->control_command); | ||||
2554 | service_serialize_exec_command(u, f, s->main_command); | ||||
2555 | |||||
2556 | r = unit_serialize_item_fd(u, f, fds, "stdin-fd", s->stdin_fd); | ||||
2557 | if (r < 0) | ||||
2558 | return r; | ||||
2559 | r = unit_serialize_item_fd(u, f, fds, "stdout-fd", s->stdout_fd); | ||||
2560 | if (r < 0) | ||||
2561 | return r; | ||||
2562 | r = unit_serialize_item_fd(u, f, fds, "stderr-fd", s->stderr_fd); | ||||
2563 | if (r < 0) | ||||
2564 | return r; | ||||
2565 | |||||
2566 | if (s->exec_fd_event_source) { | ||||
2567 | r = unit_serialize_item_fd(u, f, fds, "exec-fd", sd_event_source_get_io_fd(s->exec_fd_event_source)); | ||||
2568 | if (r < 0) | ||||
2569 | return r; | ||||
2570 | unit_serialize_item(u, f, "exec-fd-hot", yes_no(s->exec_fd_hot)); | ||||
2571 | } | ||||
2572 | |||||
2573 | if (UNIT_ISSET(s->accept_socket)(!!(s->accept_socket).target)) { | ||||
2574 | r = unit_serialize_item(u, f, "accept-socket", UNIT_DEREF(s->accept_socket)((s->accept_socket).target)->id); | ||||
2575 | if (r < 0) | ||||
2576 | return r; | ||||
2577 | } | ||||
2578 | |||||
2579 | r = unit_serialize_item_fd(u, f, fds, "socket-fd", s->socket_fd); | ||||
2580 | if (r < 0) | ||||
2581 | return r; | ||||
2582 | |||||
2583 | LIST_FOREACH(fd_store, fs, s->fd_store)for ((fs) = (s->fd_store); (fs); (fs) = (fs)->fd_store_next ) { | ||||
2584 | _cleanup_free___attribute__((cleanup(freep))) char *c = NULL((void*)0); | ||||
2585 | int copy; | ||||
2586 | |||||
2587 | copy = fdset_put_dup(fds, fs->fd); | ||||
2588 | if (copy < 0) | ||||
2589 | return copy; | ||||
2590 | |||||
2591 | c = cescape(fs->fdname); | ||||
2592 | |||||
2593 | unit_serialize_item_format(u, f, "fd-store-fd", "%i %s", copy, strempty(c)); | ||||
2594 | } | ||||
2595 | |||||
2596 | if (s->main_exec_status.pid > 0) { | ||||
2597 | unit_serialize_item_format(u, f, "main-exec-status-pid", PID_FMT"%" "i", s->main_exec_status.pid); | ||||
2598 | dual_timestamp_serialize(f, "main-exec-status-start", &s->main_exec_status.start_timestamp); | ||||
2599 | dual_timestamp_serialize(f, "main-exec-status-exit", &s->main_exec_status.exit_timestamp); | ||||
2600 | |||||
2601 | if (dual_timestamp_is_set(&s->main_exec_status.exit_timestamp)) { | ||||
2602 | unit_serialize_item_format(u, f, "main-exec-status-code", "%i", s->main_exec_status.code); | ||||
2603 | unit_serialize_item_format(u, f, "main-exec-status-status", "%i", s->main_exec_status.status); | ||||
2604 | } | ||||
2605 | } | ||||
2606 | |||||
2607 | dual_timestamp_serialize(f, "watchdog-timestamp", &s->watchdog_timestamp); | ||||
2608 | |||||
2609 | unit_serialize_item(u, f, "forbid-restart", yes_no(s->forbid_restart)); | ||||
2610 | |||||
2611 | if (s->watchdog_override_enable) | ||||
2612 | unit_serialize_item_format(u, f, "watchdog-override-usec", USEC_FMT"%" "l" "u", s->watchdog_override_usec); | ||||
2613 | |||||
2614 | return 0; | ||||
2615 | } | ||||
2616 | |||||
2617 | static int service_deserialize_exec_command(Unit *u, const char *key, const char *value) { | ||||
2618 | Service *s = SERVICE(u); | ||||
2619 | int r; | ||||
2620 | unsigned idx = 0, i; | ||||
2621 | bool_Bool control, found = false0; | ||||
2622 | ServiceExecCommand id = _SERVICE_EXEC_COMMAND_INVALID; | ||||
2623 | ExecCommand *command = NULL((void*)0); | ||||
2624 | _cleanup_free___attribute__((cleanup(freep))) char *path = NULL((void*)0); | ||||
2625 | _cleanup_strv_free___attribute__((cleanup(strv_freep))) char **argv = NULL((void*)0); | ||||
2626 | |||||
2627 | enum ExecCommandState { | ||||
2628 | STATE_EXEC_COMMAND_TYPE, | ||||
2629 | STATE_EXEC_COMMAND_INDEX, | ||||
2630 | STATE_EXEC_COMMAND_PATH, | ||||
2631 | STATE_EXEC_COMMAND_ARGS, | ||||
2632 | _STATE_EXEC_COMMAND_MAX, | ||||
2633 | _STATE_EXEC_COMMAND_INVALID = -1, | ||||
2634 | } state; | ||||
2635 | |||||
2636 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2636, __PRETTY_FUNCTION__ ); } while (0); | ||||
2637 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/core/service.c", 2637, __PRETTY_FUNCTION__ ); } while (0); | ||||
2638 | assert(value)do { if ((__builtin_expect(!!(!(value)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("value"), "../src/core/service.c", 2638, __PRETTY_FUNCTION__); } while (0); | ||||
2639 | |||||
2640 | control = streq(key, "control-command")(strcmp((key),("control-command")) == 0); | ||||
2641 | |||||
2642 | state = STATE_EXEC_COMMAND_TYPE; | ||||
2643 | |||||
2644 | for (;;) { | ||||
2645 | _cleanup_free___attribute__((cleanup(freep))) char *arg = NULL((void*)0); | ||||
2646 | |||||
2647 | r = extract_first_word(&value, &arg, NULL((void*)0), EXTRACT_CUNESCAPE); | ||||
2648 | if (r == 0) | ||||
2649 | break; | ||||
2650 | else if (r < 0) | ||||
2651 | return r; | ||||
2652 | |||||
2653 | switch (state) { | ||||
2654 | case STATE_EXEC_COMMAND_TYPE: | ||||
2655 | id = service_exec_command_from_string(arg); | ||||
2656 | if (id < 0) | ||||
2657 | return -EINVAL22; | ||||
2658 | |||||
2659 | state = STATE_EXEC_COMMAND_INDEX; | ||||
2660 | break; | ||||
2661 | case STATE_EXEC_COMMAND_INDEX: | ||||
2662 | r = safe_atou(arg, &idx); | ||||
2663 | if (r < 0) | ||||
2664 | return -EINVAL22; | ||||
2665 | |||||
2666 | state = STATE_EXEC_COMMAND_PATH; | ||||
2667 | break; | ||||
2668 | case STATE_EXEC_COMMAND_PATH: | ||||
2669 | path = TAKE_PTR(arg)({ typeof(arg) _ptr_ = (arg); (arg) = ((void*)0); _ptr_; }); | ||||
2670 | state = STATE_EXEC_COMMAND_ARGS; | ||||
2671 | |||||
2672 | if (!path_is_absolute(path)) | ||||
2673 | return -EINVAL22; | ||||
2674 | break; | ||||
2675 | case STATE_EXEC_COMMAND_ARGS: | ||||
2676 | r = strv_extend(&argv, arg); | ||||
2677 | if (r < 0) | ||||
2678 | return -ENOMEM12; | ||||
2679 | break; | ||||
2680 | default: | ||||
2681 | assert_not_reached("Unknown error at deserialization of exec command")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Unknown error at deserialization of exec command"), "../src/core/service.c" , 2681, __PRETTY_FUNCTION__); } while (0); | ||||
2682 | break; | ||||
2683 | } | ||||
2684 | } | ||||
2685 | |||||
2686 | if (state != STATE_EXEC_COMMAND_ARGS) | ||||
2687 | return -EINVAL22; | ||||
2688 | |||||
2689 | /* Let's check whether exec command on given offset matches data that we just deserialized */ | ||||
2690 | for (command = s->exec_command[id], i = 0; command; command = command->command_next, i++) { | ||||
2691 | if (i != idx) | ||||
2692 | continue; | ||||
2693 | |||||
2694 | found = strv_equal(argv, command->argv) && streq(command->path, path)(strcmp((command->path),(path)) == 0); | ||||
2695 | break; | ||||
2696 | } | ||||
2697 | |||||
2698 | if (!found) { | ||||
2699 | /* Command at the index we serialized is different, let's look for command that exactly | ||||
2700 | * matches but is on different index. If there is no such command we will not resume execution. */ | ||||
2701 | for (command = s->exec_command[id]; command; command = command->command_next) | ||||
2702 | if (strv_equal(command->argv, argv) && streq(command->path, path)(strcmp((command->path),(path)) == 0)) | ||||
2703 | break; | ||||
2704 | } | ||||
2705 | |||||
2706 | if (command && control) { | ||||
2707 | s->control_command = command; | ||||
2708 | s->control_command_id = id; | ||||
2709 | } else if (command) | ||||
2710 | s->main_command = command; | ||||
2711 | else | ||||
2712 | log_unit_warning(u, "Current command vanished from the unit file, execution of the command list won't be resumed.")({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/service.c" , 2712, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Current command vanished from the unit file, execution of the command list won't be resumed." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 2712, __func__, "Current command vanished from the unit file, execution of the command list won't be resumed." ); }); | ||||
2713 | |||||
2714 | return 0; | ||||
2715 | } | ||||
2716 | |||||
2717 | static int service_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { | ||||
2718 | Service *s = SERVICE(u); | ||||
2719 | int r; | ||||
2720 | |||||
2721 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/service.c", 2721, __PRETTY_FUNCTION__ ); } while (0); | ||||
2722 | assert(key)do { if ((__builtin_expect(!!(!(key)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("key"), "../src/core/service.c", 2722, __PRETTY_FUNCTION__ ); } while (0); | ||||
2723 | assert(value)do { if ((__builtin_expect(!!(!(value)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("value"), "../src/core/service.c", 2723, __PRETTY_FUNCTION__); } while (0); | ||||
2724 | assert(fds)do { if ((__builtin_expect(!!(!(fds)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fds"), "../src/core/service.c", 2724, __PRETTY_FUNCTION__ ); } while (0); | ||||
2725 | |||||
2726 | if (streq(key, "state")(strcmp((key),("state")) == 0)) { | ||||
2727 | ServiceState state; | ||||
2728 | |||||
2729 | state = service_state_from_string(value); | ||||
2730 | if (state < 0) | ||||
2731 | log_unit_debug(u, "Failed to parse state value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2731, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse state value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2731, __func__, "Failed to parse state value: %s", value); } ); | ||||
2732 | else | ||||
2733 | s->deserialized_state = state; | ||||
2734 | } else if (streq(key, "result")(strcmp((key),("result")) == 0)) { | ||||
2735 | ServiceResult f; | ||||
2736 | |||||
2737 | f = service_result_from_string(value); | ||||
2738 | if (f < 0) | ||||
2739 | log_unit_debug(u, "Failed to parse result value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2739, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse result value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2739, __func__, "Failed to parse result value: %s", value); }); | ||||
2740 | else if (f != SERVICE_SUCCESS) | ||||
2741 | s->result = f; | ||||
2742 | |||||
2743 | } else if (streq(key, "reload-result")(strcmp((key),("reload-result")) == 0)) { | ||||
2744 | ServiceResult f; | ||||
2745 | |||||
2746 | f = service_result_from_string(value); | ||||
2747 | if (f < 0) | ||||
2748 | log_unit_debug(u, "Failed to parse reload result value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2748, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse reload result value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2748, __func__, "Failed to parse reload result value: %s", value ); }); | ||||
2749 | else if (f != SERVICE_SUCCESS) | ||||
2750 | s->reload_result = f; | ||||
2751 | |||||
2752 | } else if (streq(key, "control-pid")(strcmp((key),("control-pid")) == 0)) { | ||||
2753 | pid_t pid; | ||||
2754 | |||||
2755 | if (parse_pid(value, &pid) < 0) | ||||
2756 | log_unit_debug(u, "Failed to parse control-pid value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2756, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse control-pid value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2756, __func__, "Failed to parse control-pid value: %s", value ); }); | ||||
2757 | else | ||||
2758 | s->control_pid = pid; | ||||
2759 | } else if (streq(key, "main-pid")(strcmp((key),("main-pid")) == 0)) { | ||||
2760 | pid_t pid; | ||||
2761 | |||||
2762 | if (parse_pid(value, &pid) < 0) | ||||
2763 | log_unit_debug(u, "Failed to parse main-pid value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2763, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse main-pid value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2763, __func__, "Failed to parse main-pid value: %s", value ); }); | ||||
2764 | else | ||||
2765 | (void) service_set_main_pid(s, pid); | ||||
2766 | } else if (streq(key, "main-pid-known")(strcmp((key),("main-pid-known")) == 0)) { | ||||
2767 | int b; | ||||
2768 | |||||
2769 | b = parse_boolean(value); | ||||
2770 | if (b < 0) | ||||
2771 | log_unit_debug(u, "Failed to parse main-pid-known value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2771, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse main-pid-known value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2771, __func__, "Failed to parse main-pid-known value: %s", value); }); | ||||
2772 | else | ||||
2773 | s->main_pid_known = b; | ||||
2774 | } else if (streq(key, "bus-name-good")(strcmp((key),("bus-name-good")) == 0)) { | ||||
2775 | int b; | ||||
2776 | |||||
2777 | b = parse_boolean(value); | ||||
2778 | if (b < 0) | ||||
2779 | log_unit_debug(u, "Failed to parse bus-name-good value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2779, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse bus-name-good value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2779, __func__, "Failed to parse bus-name-good value: %s", value ); }); | ||||
2780 | else | ||||
2781 | s->bus_name_good = b; | ||||
2782 | } else if (streq(key, "bus-name-owner")(strcmp((key),("bus-name-owner")) == 0)) { | ||||
2783 | r = free_and_strdup(&s->bus_name_owner, value); | ||||
2784 | if (r < 0) | ||||
2785 | log_unit_error_errno(u, r, "Unable to deserialize current bus owner %s: %m", value)({ const Unit *_u = (u); _u ? log_object_internal(3, r, "../src/core/service.c" , 2785, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Unable to deserialize current bus owner %s: %m", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/core/service.c" , 2785, __func__, "Unable to deserialize current bus owner %s: %m" , value); }); | ||||
2786 | } else if (streq(key, "status-text")(strcmp((key),("status-text")) == 0)) { | ||||
2787 | char *t; | ||||
2788 | |||||
2789 | r = cunescape(value, 0, &t); | ||||
2790 | if (r < 0) | ||||
2791 | log_unit_debug_errno(u, r, "Failed to unescape status text: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, r, "../src/core/service.c" , 2791, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to unescape status text: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), r, "../src/core/service.c" , 2791, __func__, "Failed to unescape status text: %s", value ); }); | ||||
2792 | else { | ||||
2793 | free(s->status_text); | ||||
2794 | s->status_text = t; | ||||
2795 | } | ||||
2796 | |||||
2797 | } else if (streq(key, "accept-socket")(strcmp((key),("accept-socket")) == 0)) { | ||||
2798 | Unit *socket; | ||||
2799 | |||||
2800 | r = manager_load_unit(u->manager, value, NULL((void*)0), NULL((void*)0), &socket); | ||||
2801 | if (r < 0) | ||||
2802 | log_unit_debug_errno(u, r, "Failed to load accept-socket unit: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, r, "../src/core/service.c" , 2802, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to load accept-socket unit: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), r, "../src/core/service.c" , 2802, __func__, "Failed to load accept-socket unit: %s", value ); }); | ||||
2803 | else { | ||||
2804 | unit_ref_set(&s->accept_socket, u, socket); | ||||
2805 | SOCKET(socket)->n_connections++; | ||||
2806 | } | ||||
2807 | |||||
2808 | } else if (streq(key, "socket-fd")(strcmp((key),("socket-fd")) == 0)) { | ||||
2809 | int fd; | ||||
2810 | |||||
2811 | if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) | ||||
2812 | log_unit_debug(u, "Failed to parse socket-fd value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2812, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse socket-fd value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2812, __func__, "Failed to parse socket-fd value: %s", value ); }); | ||||
2813 | else { | ||||
2814 | asynchronous_close(s->socket_fd); | ||||
2815 | s->socket_fd = fdset_remove(fds, fd); | ||||
2816 | } | ||||
2817 | } else if (streq(key, "fd-store-fd")(strcmp((key),("fd-store-fd")) == 0)) { | ||||
2818 | const char *fdv; | ||||
2819 | size_t pf; | ||||
2820 | int fd; | ||||
2821 | |||||
2822 | pf = strcspn(value, WHITESPACE" \t\n\r"); | ||||
2823 | fdv = strndupa(value, pf)(__extension__ ({ const char *__old = (value); size_t __len = strnlen (__old, (pf)); char *__new = (char *) __builtin_alloca (__len + 1); __new[__len] = '\0'; (char *) memcpy (__new, __old , __len); })); | ||||
2824 | |||||
2825 | if (safe_atoi(fdv, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) | ||||
2826 | log_unit_debug(u, "Failed to parse fd-store-fd value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2826, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse fd-store-fd value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2826, __func__, "Failed to parse fd-store-fd value: %s", value ); }); | ||||
2827 | else { | ||||
2828 | _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0); | ||||
2829 | const char *fdn; | ||||
2830 | |||||
2831 | fdn = value + pf; | ||||
2832 | fdn += strspn(fdn, WHITESPACE" \t\n\r"); | ||||
2833 | (void) cunescape(fdn, 0, &t); | ||||
2834 | |||||
2835 | r = service_add_fd_store(s, fd, t); | ||||
2836 | if (r < 0) | ||||
2837 | log_unit_error_errno(u, r, "Failed to add fd to store: %m")({ const Unit *_u = (u); _u ? log_object_internal(3, r, "../src/core/service.c" , 2837, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to add fd to store: %m") : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((3))), r, "../src/core/service.c", 2837, __func__ , "Failed to add fd to store: %m"); }); | ||||
2838 | else | ||||
2839 | fdset_remove(fds, fd); | ||||
2840 | } | ||||
2841 | |||||
2842 | } else if (streq(key, "main-exec-status-pid")(strcmp((key),("main-exec-status-pid")) == 0)) { | ||||
2843 | pid_t pid; | ||||
2844 | |||||
2845 | if (parse_pid(value, &pid) < 0) | ||||
2846 | log_unit_debug(u, "Failed to parse main-exec-status-pid value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2846, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse main-exec-status-pid value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2846, __func__, "Failed to parse main-exec-status-pid value: %s" , value); }); | ||||
2847 | else | ||||
2848 | s->main_exec_status.pid = pid; | ||||
2849 | } else if (streq(key, "main-exec-status-code")(strcmp((key),("main-exec-status-code")) == 0)) { | ||||
2850 | int i; | ||||
2851 | |||||
2852 | if (safe_atoi(value, &i) < 0) | ||||
2853 | log_unit_debug(u, "Failed to parse main-exec-status-code value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2853, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse main-exec-status-code value: %s", value) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))) , 0, "../src/core/service.c", 2853, __func__, "Failed to parse main-exec-status-code value: %s" , value); }); | ||||
2854 | else | ||||
2855 | s->main_exec_status.code = i; | ||||
2856 | } else if (streq(key, "main-exec-status-status")(strcmp((key),("main-exec-status-status")) == 0)) { | ||||
2857 | int i; | ||||
2858 | |||||
2859 | if (safe_atoi(value, &i) < 0) | ||||
2860 | log_unit_debug(u, "Failed to parse main-exec-status-status value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2860, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse main-exec-status-status value: %s", value) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7) )), 0, "../src/core/service.c", 2860, __func__, "Failed to parse main-exec-status-status value: %s" , value); }); | ||||
2861 | else | ||||
2862 | s->main_exec_status.status = i; | ||||
2863 | } else if (streq(key, "main-exec-status-start")(strcmp((key),("main-exec-status-start")) == 0)) | ||||
2864 | dual_timestamp_deserialize(value, &s->main_exec_status.start_timestamp); | ||||
2865 | else if (streq(key, "main-exec-status-exit")(strcmp((key),("main-exec-status-exit")) == 0)) | ||||
2866 | dual_timestamp_deserialize(value, &s->main_exec_status.exit_timestamp); | ||||
2867 | else if (streq(key, "watchdog-timestamp")(strcmp((key),("watchdog-timestamp")) == 0)) | ||||
2868 | dual_timestamp_deserialize(value, &s->watchdog_timestamp); | ||||
2869 | else if (streq(key, "forbid-restart")(strcmp((key),("forbid-restart")) == 0)) { | ||||
2870 | int b; | ||||
2871 | |||||
2872 | b = parse_boolean(value); | ||||
2873 | if (b < 0) | ||||
2874 | log_unit_debug(u, "Failed to parse forbid-restart value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2874, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse forbid-restart value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2874, __func__, "Failed to parse forbid-restart value: %s", value); }); | ||||
2875 | else | ||||
2876 | s->forbid_restart = b; | ||||
2877 | } else if (streq(key, "stdin-fd")(strcmp((key),("stdin-fd")) == 0)) { | ||||
2878 | int fd; | ||||
2879 | |||||
2880 | if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) | ||||
2881 | log_unit_debug(u, "Failed to parse stdin-fd value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2881, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse stdin-fd value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2881, __func__, "Failed to parse stdin-fd value: %s", value ); }); | ||||
2882 | else { | ||||
2883 | asynchronous_close(s->stdin_fd); | ||||
2884 | s->stdin_fd = fdset_remove(fds, fd); | ||||
2885 | s->exec_context.stdio_as_fds = true1; | ||||
2886 | } | ||||
2887 | } else if (streq(key, "stdout-fd")(strcmp((key),("stdout-fd")) == 0)) { | ||||
2888 | int fd; | ||||
2889 | |||||
2890 | if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) | ||||
2891 | log_unit_debug(u, "Failed to parse stdout-fd value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2891, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse stdout-fd value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2891, __func__, "Failed to parse stdout-fd value: %s", value ); }); | ||||
2892 | else { | ||||
2893 | asynchronous_close(s->stdout_fd); | ||||
2894 | s->stdout_fd = fdset_remove(fds, fd); | ||||
2895 | s->exec_context.stdio_as_fds = true1; | ||||
2896 | } | ||||
2897 | } else if (streq(key, "stderr-fd")(strcmp((key),("stderr-fd")) == 0)) { | ||||
2898 | int fd; | ||||
2899 | |||||
2900 | if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) | ||||
2901 | log_unit_debug(u, "Failed to parse stderr-fd value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2901, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse stderr-fd value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2901, __func__, "Failed to parse stderr-fd value: %s", value ); }); | ||||
2902 | else { | ||||
2903 | asynchronous_close(s->stderr_fd); | ||||
2904 | s->stderr_fd = fdset_remove(fds, fd); | ||||
2905 | s->exec_context.stdio_as_fds = true1; | ||||
2906 | } | ||||
2907 | } else if (streq(key, "exec-fd")(strcmp((key),("exec-fd")) == 0)) { | ||||
2908 | int fd; | ||||
2909 | |||||
2910 | if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) | ||||
2911 | log_unit_debug(u, "Failed to parse exec-fd value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2911, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse exec-fd value: %s", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2911, __func__, "Failed to parse exec-fd value: %s", value) ; }); | ||||
2912 | else { | ||||
2913 | s->exec_fd_event_source = sd_event_source_unref(s->exec_fd_event_source); | ||||
2914 | |||||
2915 | fd = fdset_remove(fds, fd); | ||||
2916 | if (service_allocate_exec_fd_event_source(s, fd, &s->exec_fd_event_source) < 0) | ||||
2917 | safe_close(fd); | ||||
2918 | } | ||||
2919 | } else if (streq(key, "watchdog-override-usec")(strcmp((key),("watchdog-override-usec")) == 0)) { | ||||
2920 | usec_t watchdog_override_usec; | ||||
2921 | if (timestamp_deserialize(value, &watchdog_override_usec) < 0) | ||||
2922 | log_unit_debug(u, "Failed to parse watchdog_override_usec value: %s", value)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2922, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse watchdog_override_usec value: %s", value) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))) , 0, "../src/core/service.c", 2922, __func__, "Failed to parse watchdog_override_usec value: %s" , value); }); | ||||
2923 | else { | ||||
2924 | s->watchdog_override_enable = true1; | ||||
2925 | s->watchdog_override_usec = watchdog_override_usec; | ||||
2926 | } | ||||
2927 | } else if (STR_IN_SET(key, "main-command", "control-command")(!!strv_find((((char**) ((const char*[]) { "main-command", "control-command" , ((void*)0) }))), (key)))) { | ||||
2928 | r = service_deserialize_exec_command(u, key, value); | ||||
2929 | if (r < 0) | ||||
2930 | log_unit_debug_errno(u, r, "Failed to parse serialized command \"%s\": %m", value)({ const Unit *_u = (u); _u ? log_object_internal(7, r, "../src/core/service.c" , 2930, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse serialized command \"%s\": %m", value) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), r, "../src/core/service.c" , 2930, __func__, "Failed to parse serialized command \"%s\": %m" , value); }); | ||||
2931 | |||||
2932 | } else if (streq(key, "n-restarts")(strcmp((key),("n-restarts")) == 0)) { | ||||
2933 | r = safe_atou(value, &s->n_restarts); | ||||
2934 | if (r < 0) | ||||
2935 | log_unit_debug_errno(u, r, "Failed to parse serialized restart counter '%s': %m", value)({ const Unit *_u = (u); _u ? log_object_internal(7, r, "../src/core/service.c" , 2935, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse serialized restart counter '%s': %m", value ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7 ))), r, "../src/core/service.c", 2935, __func__, "Failed to parse serialized restart counter '%s': %m" , value); }); | ||||
2936 | |||||
2937 | } else if (streq(key, "flush-n-restarts")(strcmp((key),("flush-n-restarts")) == 0)) { | ||||
2938 | r = parse_boolean(value); | ||||
2939 | if (r < 0) | ||||
2940 | log_unit_debug_errno(u, r, "Failed to parse serialized flush restart counter setting '%s': %m", value)({ const Unit *_u = (u); _u ? log_object_internal(7, r, "../src/core/service.c" , 2940, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse serialized flush restart counter setting '%s': %m" , value) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), r, "../src/core/service.c", 2940, __func__, "Failed to parse serialized flush restart counter setting '%s': %m" , value); }); | ||||
2941 | else | ||||
2942 | s->flush_n_restarts = r; | ||||
2943 | } else | ||||
2944 | log_unit_debug(u, "Unknown serialization key: %s", key)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 2944, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Unknown serialization key: %s", key) : log_internal_realm( ((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 2944, __func__, "Unknown serialization key: %s", key); }); | ||||
2945 | |||||
2946 | return 0; | ||||
2947 | } | ||||
2948 | |||||
2949 | _pure___attribute__ ((pure)) static UnitActiveState service_active_state(Unit *u) { | ||||
2950 | const UnitActiveState *table; | ||||
2951 | |||||
2952 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/service.c", 2952, __PRETTY_FUNCTION__ ); } while (0); | ||||
2953 | |||||
2954 | table = SERVICE(u)->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table; | ||||
2955 | |||||
2956 | return table[SERVICE(u)->state]; | ||||
2957 | } | ||||
2958 | |||||
2959 | static const char *service_sub_state_to_string(Unit *u) { | ||||
2960 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/service.c", 2960, __PRETTY_FUNCTION__ ); } while (0); | ||||
2961 | |||||
2962 | return service_state_to_string(SERVICE(u)->state); | ||||
2963 | } | ||||
2964 | |||||
2965 | static bool_Bool service_may_gc(Unit *u) { | ||||
2966 | Service *s = SERVICE(u); | ||||
2967 | |||||
2968 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 2968, __PRETTY_FUNCTION__ ); } while (0); | ||||
2969 | |||||
2970 | /* Never clean up services that still have a process around, even if the service is formally dead. Note that | ||||
2971 | * unit_may_gc() already checked our cgroup for us, we just check our two additional PIDs, too, in case they | ||||
2972 | * have moved outside of the cgroup. */ | ||||
2973 | |||||
2974 | if (main_pid_good(s) > 0 || | ||||
2975 | control_pid_good(s) > 0) | ||||
2976 | return false0; | ||||
2977 | |||||
2978 | return true1; | ||||
2979 | } | ||||
2980 | |||||
2981 | static int service_retry_pid_file(Service *s) { | ||||
2982 | int r; | ||||
2983 | |||||
2984 | assert(s->pid_file)do { if ((__builtin_expect(!!(!(s->pid_file)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s->pid_file"), "../src/core/service.c" , 2984, __PRETTY_FUNCTION__); } while (0); | ||||
2985 | assert(IN_SET(s->state, SERVICE_START, SERVICE_START_POST))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST})/sizeof( int)]; switch(s->state) { case SERVICE_START: case SERVICE_START_POST : _found = 1; break; default: break; } _found; }))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("IN_SET(s->state, SERVICE_START, SERVICE_START_POST)" ), "../src/core/service.c", 2985, __PRETTY_FUNCTION__); } while (0); | ||||
2986 | |||||
2987 | r = service_load_pid_file(s, false0); | ||||
2988 | if (r < 0) | ||||
2989 | return r; | ||||
2990 | |||||
2991 | service_unwatch_pid_file(s); | ||||
2992 | |||||
2993 | service_enter_running(s, SERVICE_SUCCESS); | ||||
2994 | return 0; | ||||
2995 | } | ||||
2996 | |||||
2997 | static int service_watch_pid_file(Service *s) { | ||||
2998 | int r; | ||||
2999 | |||||
3000 | log_unit_debug(UNIT(s), "Setting watch for PID file %s", s->pid_file_pathspec->path)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 3000, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Setting watch for PID file %s" , s->pid_file_pathspec->path) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((7))), 0, "../src/core/service.c", 3000, __func__ , "Setting watch for PID file %s", s->pid_file_pathspec-> path); }); | ||||
3001 | |||||
3002 | r = path_spec_watch(s->pid_file_pathspec, service_dispatch_inotify_io); | ||||
3003 | if (r < 0) | ||||
3004 | goto fail; | ||||
3005 | |||||
3006 | /* the pidfile might have appeared just before we set the watch */ | ||||
3007 | log_unit_debug(UNIT(s), "Trying to read PID file %s in case it changed", s->pid_file_pathspec->path)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 3007, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Trying to read PID file %s in case it changed" , s->pid_file_pathspec->path) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((7))), 0, "../src/core/service.c", 3007, __func__ , "Trying to read PID file %s in case it changed", s->pid_file_pathspec ->path); }); | ||||
3008 | service_retry_pid_file(s); | ||||
3009 | |||||
3010 | return 0; | ||||
3011 | fail: | ||||
3012 | log_unit_error_errno(UNIT(s), r, "Failed to set a watch for PID file %s: %m", s->pid_file_pathspec->path)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, r, "../src/core/service.c", 3012, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to set a watch for PID file %s: %m" , s->pid_file_pathspec->path) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((3))), r, "../src/core/service.c", 3012, __func__ , "Failed to set a watch for PID file %s: %m", s->pid_file_pathspec ->path); }); | ||||
3013 | service_unwatch_pid_file(s); | ||||
3014 | return r; | ||||
3015 | } | ||||
3016 | |||||
3017 | static int service_demand_pid_file(Service *s) { | ||||
3018 | PathSpec *ps; | ||||
3019 | |||||
3020 | assert(s->pid_file)do { if ((__builtin_expect(!!(!(s->pid_file)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s->pid_file"), "../src/core/service.c" , 3020, __PRETTY_FUNCTION__); } while (0); | ||||
3021 | assert(!s->pid_file_pathspec)do { if ((__builtin_expect(!!(!(!s->pid_file_pathspec)),0) )) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!s->pid_file_pathspec" ), "../src/core/service.c", 3021, __PRETTY_FUNCTION__); } while (0); | ||||
3022 | |||||
3023 | ps = new0(PathSpec, 1)((PathSpec*) calloc((1), sizeof(PathSpec))); | ||||
3024 | if (!ps) | ||||
3025 | return -ENOMEM12; | ||||
3026 | |||||
3027 | ps->unit = UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }); | ||||
3028 | ps->path = strdup(s->pid_file); | ||||
3029 | if (!ps->path) { | ||||
3030 | free(ps); | ||||
3031 | return -ENOMEM12; | ||||
3032 | } | ||||
3033 | |||||
3034 | path_simplify(ps->path, false0); | ||||
3035 | |||||
3036 | /* PATH_CHANGED would not be enough. There are daemons (sendmail) that | ||||
3037 | * keep their PID file open all the time. */ | ||||
3038 | ps->type = PATH_MODIFIED; | ||||
3039 | ps->inotify_fd = -1; | ||||
3040 | |||||
3041 | s->pid_file_pathspec = ps; | ||||
3042 | |||||
3043 | return service_watch_pid_file(s); | ||||
3044 | } | ||||
3045 | |||||
3046 | static int service_dispatch_inotify_io(sd_event_source *source, int fd, uint32_t events, void *userdata) { | ||||
3047 | PathSpec *p = userdata; | ||||
3048 | Service *s; | ||||
3049 | |||||
3050 | assert(p)do { if ((__builtin_expect(!!(!(p)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("p"), "../src/core/service.c", 3050, __PRETTY_FUNCTION__ ); } while (0); | ||||
3051 | |||||
3052 | s = SERVICE(p->unit); | ||||
3053 | |||||
3054 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 3054, __PRETTY_FUNCTION__ ); } while (0); | ||||
3055 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/core/service.c", 3055 , __PRETTY_FUNCTION__); } while (0); | ||||
3056 | assert(IN_SET(s->state, SERVICE_START, SERVICE_START_POST))do { if ((__builtin_expect(!!(!(({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended[20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST})/sizeof( int)]; switch(s->state) { case SERVICE_START: case SERVICE_START_POST : _found = 1; break; default: break; } _found; }))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("IN_SET(s->state, SERVICE_START, SERVICE_START_POST)" ), "../src/core/service.c", 3056, __PRETTY_FUNCTION__); } while (0); | ||||
3057 | assert(s->pid_file_pathspec)do { if ((__builtin_expect(!!(!(s->pid_file_pathspec)),0)) ) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("s->pid_file_pathspec" ), "../src/core/service.c", 3057, __PRETTY_FUNCTION__); } while (0); | ||||
3058 | assert(path_spec_owns_inotify_fd(s->pid_file_pathspec, fd))do { if ((__builtin_expect(!!(!(path_spec_owns_inotify_fd(s-> pid_file_pathspec, fd))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("path_spec_owns_inotify_fd(s->pid_file_pathspec, fd)"), "../src/core/service.c", 3058, __PRETTY_FUNCTION__); } while (0); | ||||
3059 | |||||
3060 | log_unit_debug(UNIT(s), "inotify event")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 3060, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "inotify event") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 3060, __func__, "inotify event"); }); | ||||
3061 | |||||
3062 | if (path_spec_fd_event(p, events) < 0) | ||||
3063 | goto fail; | ||||
3064 | |||||
3065 | if (service_retry_pid_file(s) == 0) | ||||
3066 | return 0; | ||||
3067 | |||||
3068 | if (service_watch_pid_file(s) < 0) | ||||
3069 | goto fail; | ||||
3070 | |||||
3071 | return 0; | ||||
3072 | |||||
3073 | fail: | ||||
3074 | service_unwatch_pid_file(s); | ||||
3075 | service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES); | ||||
3076 | return 0; | ||||
3077 | } | ||||
3078 | |||||
3079 | static int service_dispatch_exec_io(sd_event_source *source, int fd, uint32_t events, void *userdata) { | ||||
3080 | Service *s = SERVICE(userdata); | ||||
3081 | |||||
3082 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 3082, __PRETTY_FUNCTION__ ); } while (0); | ||||
3083 | |||||
3084 | log_unit_debug(UNIT(s), "got exec-fd event")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 3084, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "got exec-fd event") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 3084, __func__, "got exec-fd event"); }); | ||||
3085 | |||||
3086 | /* If Type=exec is set, we'll consider a service started successfully the instant we invoked execve() | ||||
3087 | * successfully for it. We implement this through a pipe() towards the child, which the kernel automatically | ||||
3088 | * closes for us due to O_CLOEXEC on execve() in the child, which then triggers EOF on the pipe in the | ||||
3089 | * parent. We need to be careful however, as there are other reasons that we might cause the child's side of | ||||
3090 | * the pipe to be closed (for example, a simple exit()). To deal with that we'll ignore EOFs on the pipe unless | ||||
3091 | * the child signalled us first that it is about to call the execve(). It does so by sending us a simple | ||||
3092 | * non-zero byte via the pipe. We also provide the child with a way to inform us in case execve() failed: if it | ||||
3093 | * sends a zero byte we'll ignore POLLHUP on the fd again. */ | ||||
3094 | |||||
3095 | for (;;) { | ||||
3096 | uint8_t x; | ||||
3097 | ssize_t n; | ||||
3098 | |||||
3099 | n = read(fd, &x, sizeof(x)); | ||||
3100 | if (n < 0) { | ||||
3101 | if (errno(*__errno_location ()) == EAGAIN11) /* O_NONBLOCK in effect → everything queued has now been processed. */ | ||||
3102 | return 0; | ||||
3103 | |||||
3104 | return log_unit_error_errno(UNIT(s), errno, "Failed to read from exec_fd: %m")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, (*__errno_location ()), "../src/core/service.c", 3104, __func__ , _u->manager->unit_log_field, _u->id, _u->manager ->invocation_log_field, _u->invocation_id_string, "Failed to read from exec_fd: %m" ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((3 ))), (*__errno_location ()), "../src/core/service.c", 3104, __func__ , "Failed to read from exec_fd: %m"); }); | ||||
3105 | } | ||||
3106 | if (n == 0) { /* EOF → the event we are waiting for */ | ||||
3107 | |||||
3108 | s->exec_fd_event_source = sd_event_source_unref(s->exec_fd_event_source); | ||||
3109 | |||||
3110 | if (s->exec_fd_hot) { /* Did the child tell us to expect EOF now? */ | ||||
3111 | log_unit_debug(UNIT(s), "Got EOF on exec-fd")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 3111, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got EOF on exec-fd") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 3111, __func__, "Got EOF on exec-fd"); }); | ||||
3112 | |||||
3113 | s->exec_fd_hot = false0; | ||||
3114 | |||||
3115 | /* Nice! This is what we have been waiting for. Transition to next state. */ | ||||
3116 | if (s->type == SERVICE_EXEC && s->state == SERVICE_START) | ||||
3117 | service_enter_start_post(s); | ||||
3118 | } else | ||||
3119 | log_unit_debug(UNIT(s), "Got EOF on exec-fd while it was disabled, ignoring.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (7, 0, "../src/core/service.c", 3119, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got EOF on exec-fd while it was disabled, ignoring." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7 ))), 0, "../src/core/service.c", 3119, __func__, "Got EOF on exec-fd while it was disabled, ignoring." ); }); | ||||
3120 | |||||
3121 | return 0; | ||||
3122 | } | ||||
3123 | |||||
3124 | /* A byte was read → this turns on/off the exec fd logic */ | ||||
3125 | assert(n == sizeof(x))do { if ((__builtin_expect(!!(!(n == sizeof(x))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("n == sizeof(x)"), "../src/core/service.c" , 3125, __PRETTY_FUNCTION__); } while (0); | ||||
3126 | s->exec_fd_hot = x; | ||||
3127 | } | ||||
3128 | |||||
3129 | return 0; | ||||
3130 | } | ||||
3131 | |||||
3132 | static void service_notify_cgroup_empty_event(Unit *u) { | ||||
3133 | Service *s = SERVICE(u); | ||||
3134 | |||||
3135 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/service.c", 3135, __PRETTY_FUNCTION__ ); } while (0); | ||||
3136 | |||||
3137 | log_unit_debug(u, "cgroup is empty")({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 3137, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "cgroup is empty") : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((7))), 0, "../src/core/service.c", 3137, __func__ , "cgroup is empty"); }); | ||||
3138 | |||||
3139 | switch (s->state) { | ||||
3140 | |||||
3141 | /* Waiting for SIGCHLD is usually more interesting, | ||||
3142 | * because it includes return codes/signals. Which is | ||||
3143 | * why we ignore the cgroup events for most cases, | ||||
3144 | * except when we don't know pid which to expect the | ||||
3145 | * SIGCHLD for. */ | ||||
3146 | |||||
3147 | case SERVICE_START: | ||||
3148 | if (s->type == SERVICE_NOTIFY && | ||||
3149 | main_pid_good(s) == 0 && | ||||
3150 | control_pid_good(s) == 0) { | ||||
3151 | /* No chance of getting a ready notification anymore */ | ||||
3152 | service_enter_stop_post(s, SERVICE_FAILURE_PROTOCOL); | ||||
3153 | break; | ||||
3154 | } | ||||
3155 | |||||
3156 | _fallthrough_; | ||||
3157 | case SERVICE_START_POST: | ||||
3158 | if (s->pid_file_pathspec && | ||||
3159 | main_pid_good(s) == 0 && | ||||
3160 | control_pid_good(s) == 0) { | ||||
3161 | |||||
3162 | /* Give up hoping for the daemon to write its PID file */ | ||||
3163 | log_unit_warning(u, "Daemon never wrote its PID file. Failing.")({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/service.c" , 3163, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Daemon never wrote its PID file. Failing.") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/service.c" , 3163, __func__, "Daemon never wrote its PID file. Failing." ); }); | ||||
3164 | |||||
3165 | service_unwatch_pid_file(s); | ||||
3166 | if (s->state == SERVICE_START) | ||||
3167 | service_enter_stop_post(s, SERVICE_FAILURE_PROTOCOL); | ||||
3168 | else | ||||
3169 | service_enter_stop(s, SERVICE_FAILURE_PROTOCOL); | ||||
3170 | } | ||||
3171 | break; | ||||
3172 | |||||
3173 | case SERVICE_RUNNING: | ||||
3174 | /* service_enter_running() will figure out what to do */ | ||||
3175 | service_enter_running(s, SERVICE_SUCCESS); | ||||
3176 | break; | ||||
3177 | |||||
3178 | case SERVICE_STOP_SIGABRT: | ||||
3179 | case SERVICE_STOP_SIGTERM: | ||||
3180 | case SERVICE_STOP_SIGKILL: | ||||
3181 | |||||
3182 | if (main_pid_good(s) <= 0 && control_pid_good(s) <= 0) | ||||
3183 | service_enter_stop_post(s, SERVICE_SUCCESS); | ||||
3184 | |||||
3185 | break; | ||||
3186 | |||||
3187 | case SERVICE_STOP_POST: | ||||
3188 | case SERVICE_FINAL_SIGTERM: | ||||
3189 | case SERVICE_FINAL_SIGKILL: | ||||
3190 | if (main_pid_good(s) <= 0 && control_pid_good(s) <= 0) | ||||
3191 | service_enter_dead(s, SERVICE_SUCCESS, true1); | ||||
3192 | |||||
3193 | break; | ||||
3194 | |||||
3195 | default: | ||||
3196 | ; | ||||
3197 | } | ||||
3198 | } | ||||
3199 | |||||
3200 | static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { | ||||
3201 | bool_Bool notify_dbus = true1; | ||||
3202 | Service *s = SERVICE(u); | ||||
3203 | ServiceResult f; | ||||
3204 | |||||
3205 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 3205, __PRETTY_FUNCTION__ ); } while (0); | ||||
3206 | assert(pid >= 0)do { if ((__builtin_expect(!!(!(pid >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("pid >= 0"), "../src/core/service.c", 3206, __PRETTY_FUNCTION__); } while (0); | ||||
3207 | |||||
3208 | if (is_clean_exit(code, status, s->type == SERVICE_ONESHOT ? EXIT_CLEAN_COMMAND : EXIT_CLEAN_DAEMON, &s->success_status)) | ||||
3209 | f = SERVICE_SUCCESS; | ||||
3210 | else if (code == CLD_EXITEDCLD_EXITED) | ||||
3211 | f = SERVICE_FAILURE_EXIT_CODE; | ||||
3212 | else if (code == CLD_KILLEDCLD_KILLED) | ||||
3213 | f = SERVICE_FAILURE_SIGNAL; | ||||
3214 | else if (code == CLD_DUMPEDCLD_DUMPED) | ||||
3215 | f = SERVICE_FAILURE_CORE_DUMP; | ||||
3216 | else | ||||
3217 | assert_not_reached("Unknown code")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Unknown code"), "../src/core/service.c", 3217, __PRETTY_FUNCTION__ ); } while (0); | ||||
3218 | |||||
3219 | if (s->main_pid == pid) { | ||||
3220 | /* Forking services may occasionally move to a new PID. | ||||
3221 | * As long as they update the PID file before exiting the old | ||||
3222 | * PID, they're fine. */ | ||||
3223 | if (service_load_pid_file(s, false0) > 0) | ||||
3224 | return; | ||||
3225 | |||||
3226 | s->main_pid = 0; | ||||
3227 | exec_status_exit(&s->main_exec_status, &s->exec_context, pid, code, status); | ||||
3228 | |||||
3229 | if (s->main_command) { | ||||
3230 | /* If this is not a forking service than the | ||||
3231 | * main process got started and hence we copy | ||||
3232 | * the exit status so that it is recorded both | ||||
3233 | * as main and as control process exit | ||||
3234 | * status */ | ||||
3235 | |||||
3236 | s->main_command->exec_status = s->main_exec_status; | ||||
3237 | |||||
3238 | if (s->main_command->flags & EXEC_COMMAND_IGNORE_FAILURE) | ||||
3239 | f = SERVICE_SUCCESS; | ||||
3240 | } else if (s->exec_command[SERVICE_EXEC_START]) { | ||||
3241 | |||||
3242 | /* If this is a forked process, then we should | ||||
3243 | * ignore the return value if this was | ||||
3244 | * configured for the starter process */ | ||||
3245 | |||||
3246 | if (s->exec_command[SERVICE_EXEC_START]->flags & EXEC_COMMAND_IGNORE_FAILURE) | ||||
3247 | f = SERVICE_SUCCESS; | ||||
3248 | } | ||||
3249 | |||||
3250 | /* When this is a successful exit, let's log about the exit code on DEBUG level. If this is a failure | ||||
3251 | * and the process exited on its own via exit(), then let's make this a NOTICE, under the assumption | ||||
3252 | * that the service already logged the reason at a higher log level on its own. However, if the service | ||||
3253 | * died due to a signal, then it most likely didn't say anything about any reason, hence let's raise | ||||
3254 | * our log level to WARNING then. */ | ||||
3255 | |||||
3256 | log_struct(f == SERVICE_SUCCESS ? LOG_DEBUG :log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (f == SERVICE_SUCCESS ? 7 : (code == CLD_EXITED ? 5 : 4))), 0, "../src/core/service.c" , 3266, __func__, "MESSAGE=%s: " "Main process exited, code=%s, status=%i/%s" , (u)->id, sigchld_code_to_string(code), status, strna(code == CLD_EXITED ? exit_status_to_string(status, EXIT_STATUS_FULL ) : signal_to_string(status)), "EXIT_CODE=%s", sigchld_code_to_string (code), "EXIT_STATUS=%i", status, (u)->manager->unit_log_format_string , (u)->id, (u)->manager->invocation_log_format_string , (u)->invocation_id_string, ((void*)0)) | ||||
3257 | (code == CLD_EXITED ? LOG_NOTICE : LOG_WARNING),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (f == SERVICE_SUCCESS ? 7 : (code == CLD_EXITED ? 5 : 4))), 0, "../src/core/service.c" , 3266, __func__, "MESSAGE=%s: " "Main process exited, code=%s, status=%i/%s" , (u)->id, sigchld_code_to_string(code), status, strna(code == CLD_EXITED ? exit_status_to_string(status, EXIT_STATUS_FULL ) : signal_to_string(status)), "EXIT_CODE=%s", sigchld_code_to_string (code), "EXIT_STATUS=%i", status, (u)->manager->unit_log_format_string , (u)->id, (u)->manager->invocation_log_format_string , (u)->invocation_id_string, ((void*)0)) | ||||
3258 | LOG_UNIT_MESSAGE(u, "Main process exited, code=%s, status=%i/%s",log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (f == SERVICE_SUCCESS ? 7 : (code == CLD_EXITED ? 5 : 4))), 0, "../src/core/service.c" , 3266, __func__, "MESSAGE=%s: " "Main process exited, code=%s, status=%i/%s" , (u)->id, sigchld_code_to_string(code), status, strna(code == CLD_EXITED ? exit_status_to_string(status, EXIT_STATUS_FULL ) : signal_to_string(status)), "EXIT_CODE=%s", sigchld_code_to_string (code), "EXIT_STATUS=%i", status, (u)->manager->unit_log_format_string , (u)->id, (u)->manager->invocation_log_format_string , (u)->invocation_id_string, ((void*)0)) | ||||
3259 | sigchld_code_to_string(code), status,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (f == SERVICE_SUCCESS ? 7 : (code == CLD_EXITED ? 5 : 4))), 0, "../src/core/service.c" , 3266, __func__, "MESSAGE=%s: " "Main process exited, code=%s, status=%i/%s" , (u)->id, sigchld_code_to_string(code), status, strna(code == CLD_EXITED ? exit_status_to_string(status, EXIT_STATUS_FULL ) : signal_to_string(status)), "EXIT_CODE=%s", sigchld_code_to_string (code), "EXIT_STATUS=%i", status, (u)->manager->unit_log_format_string , (u)->id, (u)->manager->invocation_log_format_string , (u)->invocation_id_string, ((void*)0)) | ||||
3260 | strna(code == CLD_EXITEDlog_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (f == SERVICE_SUCCESS ? 7 : (code == CLD_EXITED ? 5 : 4))), 0, "../src/core/service.c" , 3266, __func__, "MESSAGE=%s: " "Main process exited, code=%s, status=%i/%s" , (u)->id, sigchld_code_to_string(code), status, strna(code == CLD_EXITED ? exit_status_to_string(status, EXIT_STATUS_FULL ) : signal_to_string(status)), "EXIT_CODE=%s", sigchld_code_to_string (code), "EXIT_STATUS=%i", status, (u)->manager->unit_log_format_string , (u)->id, (u)->manager->invocation_log_format_string , (u)->invocation_id_string, ((void*)0)) | ||||
3261 | ? exit_status_to_string(status, EXIT_STATUS_FULL)log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (f == SERVICE_SUCCESS ? 7 : (code == CLD_EXITED ? 5 : 4))), 0, "../src/core/service.c" , 3266, __func__, "MESSAGE=%s: " "Main process exited, code=%s, status=%i/%s" , (u)->id, sigchld_code_to_string(code), status, strna(code == CLD_EXITED ? exit_status_to_string(status, EXIT_STATUS_FULL ) : signal_to_string(status)), "EXIT_CODE=%s", sigchld_code_to_string (code), "EXIT_STATUS=%i", status, (u)->manager->unit_log_format_string , (u)->id, (u)->manager->invocation_log_format_string , (u)->invocation_id_string, ((void*)0)) | ||||
3262 | : signal_to_string(status))),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (f == SERVICE_SUCCESS ? 7 : (code == CLD_EXITED ? 5 : 4))), 0, "../src/core/service.c" , 3266, __func__, "MESSAGE=%s: " "Main process exited, code=%s, status=%i/%s" , (u)->id, sigchld_code_to_string(code), status, strna(code == CLD_EXITED ? exit_status_to_string(status, EXIT_STATUS_FULL ) : signal_to_string(status)), "EXIT_CODE=%s", sigchld_code_to_string (code), "EXIT_STATUS=%i", status, (u)->manager->unit_log_format_string , (u)->id, (u)->manager->invocation_log_format_string , (u)->invocation_id_string, ((void*)0)) | ||||
3263 | "EXIT_CODE=%s", sigchld_code_to_string(code),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (f == SERVICE_SUCCESS ? 7 : (code == CLD_EXITED ? 5 : 4))), 0, "../src/core/service.c" , 3266, __func__, "MESSAGE=%s: " "Main process exited, code=%s, status=%i/%s" , (u)->id, sigchld_code_to_string(code), status, strna(code == CLD_EXITED ? exit_status_to_string(status, EXIT_STATUS_FULL ) : signal_to_string(status)), "EXIT_CODE=%s", sigchld_code_to_string (code), "EXIT_STATUS=%i", status, (u)->manager->unit_log_format_string , (u)->id, (u)->manager->invocation_log_format_string , (u)->invocation_id_string, ((void*)0)) | ||||
3264 | "EXIT_STATUS=%i", status,log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (f == SERVICE_SUCCESS ? 7 : (code == CLD_EXITED ? 5 : 4))), 0, "../src/core/service.c" , 3266, __func__, "MESSAGE=%s: " "Main process exited, code=%s, status=%i/%s" , (u)->id, sigchld_code_to_string(code), status, strna(code == CLD_EXITED ? exit_status_to_string(status, EXIT_STATUS_FULL ) : signal_to_string(status)), "EXIT_CODE=%s", sigchld_code_to_string (code), "EXIT_STATUS=%i", status, (u)->manager->unit_log_format_string , (u)->id, (u)->manager->invocation_log_format_string , (u)->invocation_id_string, ((void*)0)) | ||||
3265 | LOG_UNIT_ID(u),log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (f == SERVICE_SUCCESS ? 7 : (code == CLD_EXITED ? 5 : 4))), 0, "../src/core/service.c" , 3266, __func__, "MESSAGE=%s: " "Main process exited, code=%s, status=%i/%s" , (u)->id, sigchld_code_to_string(code), status, strna(code == CLD_EXITED ? exit_status_to_string(status, EXIT_STATUS_FULL ) : signal_to_string(status)), "EXIT_CODE=%s", sigchld_code_to_string (code), "EXIT_STATUS=%i", status, (u)->manager->unit_log_format_string , (u)->id, (u)->manager->invocation_log_format_string , (u)->invocation_id_string, ((void*)0)) | ||||
3266 | LOG_UNIT_INVOCATION_ID(u))log_struct_internal(((LOG_REALM_SYSTEMD) << 10 | (f == SERVICE_SUCCESS ? 7 : (code == CLD_EXITED ? 5 : 4))), 0, "../src/core/service.c" , 3266, __func__, "MESSAGE=%s: " "Main process exited, code=%s, status=%i/%s" , (u)->id, sigchld_code_to_string(code), status, strna(code == CLD_EXITED ? exit_status_to_string(status, EXIT_STATUS_FULL ) : signal_to_string(status)), "EXIT_CODE=%s", sigchld_code_to_string (code), "EXIT_STATUS=%i", status, (u)->manager->unit_log_format_string , (u)->id, (u)->manager->invocation_log_format_string , (u)->invocation_id_string, ((void*)0)); | ||||
3267 | |||||
3268 | if (s->result == SERVICE_SUCCESS) | ||||
3269 | s->result = f; | ||||
3270 | |||||
3271 | if (s->main_command && | ||||
3272 | s->main_command->command_next && | ||||
3273 | s->type == SERVICE_ONESHOT && | ||||
3274 | f == SERVICE_SUCCESS) { | ||||
3275 | |||||
3276 | /* There is another command to * | ||||
3277 | * execute, so let's do that. */ | ||||
3278 | |||||
3279 | log_unit_debug(u, "Running next main command for state %s.", service_state_to_string(s->state))({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 3279, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Running next main command for state %s.", service_state_to_string (s->state)) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 3279, __func__, "Running next main command for state %s." , service_state_to_string(s->state)); }); | ||||
3280 | service_run_next_main(s); | ||||
3281 | |||||
3282 | } else { | ||||
3283 | |||||
3284 | /* The service exited, so the service is officially | ||||
3285 | * gone. */ | ||||
3286 | s->main_command = NULL((void*)0); | ||||
3287 | |||||
3288 | switch (s->state) { | ||||
3289 | |||||
3290 | case SERVICE_START_POST: | ||||
3291 | case SERVICE_RELOAD: | ||||
3292 | case SERVICE_STOP: | ||||
3293 | /* Need to wait until the operation is | ||||
3294 | * done */ | ||||
3295 | break; | ||||
3296 | |||||
3297 | case SERVICE_START: | ||||
3298 | if (s->type == SERVICE_ONESHOT) { | ||||
3299 | /* This was our main goal, so let's go on */ | ||||
3300 | if (f == SERVICE_SUCCESS) | ||||
3301 | service_enter_start_post(s); | ||||
3302 | else | ||||
3303 | service_enter_signal(s, SERVICE_STOP_SIGTERM, f); | ||||
3304 | break; | ||||
3305 | } else if (s->type == SERVICE_NOTIFY) { | ||||
3306 | /* Only enter running through a notification, so that the | ||||
3307 | * SERVICE_START state signifies that no ready notification | ||||
3308 | * has been received */ | ||||
3309 | if (f != SERVICE_SUCCESS) | ||||
3310 | service_enter_signal(s, SERVICE_STOP_SIGTERM, f); | ||||
3311 | else if (!s->remain_after_exit || s->notify_access == NOTIFY_MAIN) | ||||
3312 | /* The service has never been and will never be active */ | ||||
3313 | service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_PROTOCOL); | ||||
3314 | break; | ||||
3315 | } | ||||
3316 | |||||
3317 | _fallthrough_; | ||||
3318 | case SERVICE_RUNNING: | ||||
3319 | service_enter_running(s, f); | ||||
3320 | break; | ||||
3321 | |||||
3322 | case SERVICE_STOP_SIGABRT: | ||||
3323 | case SERVICE_STOP_SIGTERM: | ||||
3324 | case SERVICE_STOP_SIGKILL: | ||||
3325 | |||||
3326 | if (control_pid_good(s) <= 0) | ||||
3327 | service_enter_stop_post(s, f); | ||||
3328 | |||||
3329 | /* If there is still a control process, wait for that first */ | ||||
3330 | break; | ||||
3331 | |||||
3332 | case SERVICE_STOP_POST: | ||||
3333 | |||||
3334 | if (control_pid_good(s) <= 0) | ||||
3335 | service_enter_signal(s, SERVICE_FINAL_SIGTERM, f); | ||||
3336 | |||||
3337 | break; | ||||
3338 | |||||
3339 | case SERVICE_FINAL_SIGTERM: | ||||
3340 | case SERVICE_FINAL_SIGKILL: | ||||
3341 | |||||
3342 | if (control_pid_good(s) <= 0) | ||||
3343 | service_enter_dead(s, f, true1); | ||||
3344 | break; | ||||
3345 | |||||
3346 | default: | ||||
3347 | assert_not_reached("Uh, main process died at wrong time.")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Uh, main process died at wrong time."), "../src/core/service.c" , 3347, __PRETTY_FUNCTION__); } while (0); | ||||
3348 | } | ||||
3349 | } | ||||
3350 | |||||
3351 | } else if (s->control_pid == pid) { | ||||
3352 | s->control_pid = 0; | ||||
3353 | |||||
3354 | /* ExecCondition= calls that exit with (0, 254] should invoke skip-like behavior instead of failing */ | ||||
3355 | if (f == SERVICE_FAILURE_EXIT_CODE && s->state == SERVICE_CONDITION && status < 255) | ||||
3356 | f = SERVICE_SKIP_CONDITION; | ||||
3357 | |||||
3358 | if (s->control_command) { | ||||
3359 | exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status); | ||||
3360 | |||||
3361 | if (s->control_command->flags & EXEC_COMMAND_IGNORE_FAILURE) | ||||
3362 | f = SERVICE_SUCCESS; | ||||
3363 | } | ||||
3364 | |||||
3365 | log_unit_full(u, f == SERVICE_SUCCESS ? LOG_DEBUG : LOG_NOTICE, 0,({ const Unit *_u = (u); _u ? log_object_internal(f == SERVICE_SUCCESS ? 7 : 5, 0, "../src/core/service.c", 3367, __func__, _u-> manager->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Control process exited, code=%s status=%i" , sigchld_code_to_string(code), status) : log_internal_realm( ((LOG_REALM_SYSTEMD) << 10 | ((f == SERVICE_SUCCESS ? 7 : 5))), 0, "../src/core/service.c", 3367, __func__, "Control process exited, code=%s status=%i" , sigchld_code_to_string(code), status); }) | ||||
3366 | "Control process exited, code=%s status=%i",({ const Unit *_u = (u); _u ? log_object_internal(f == SERVICE_SUCCESS ? 7 : 5, 0, "../src/core/service.c", 3367, __func__, _u-> manager->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Control process exited, code=%s status=%i" , sigchld_code_to_string(code), status) : log_internal_realm( ((LOG_REALM_SYSTEMD) << 10 | ((f == SERVICE_SUCCESS ? 7 : 5))), 0, "../src/core/service.c", 3367, __func__, "Control process exited, code=%s status=%i" , sigchld_code_to_string(code), status); }) | ||||
3367 | sigchld_code_to_string(code), status)({ const Unit *_u = (u); _u ? log_object_internal(f == SERVICE_SUCCESS ? 7 : 5, 0, "../src/core/service.c", 3367, __func__, _u-> manager->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Control process exited, code=%s status=%i" , sigchld_code_to_string(code), status) : log_internal_realm( ((LOG_REALM_SYSTEMD) << 10 | ((f == SERVICE_SUCCESS ? 7 : 5))), 0, "../src/core/service.c", 3367, __func__, "Control process exited, code=%s status=%i" , sigchld_code_to_string(code), status); }); | ||||
3368 | |||||
3369 | if (s->state != SERVICE_RELOAD && s->result == SERVICE_SUCCESS) | ||||
3370 | s->result = f; | ||||
3371 | |||||
3372 | if (s->control_command && | ||||
3373 | s->control_command->command_next && | ||||
3374 | f == SERVICE_SUCCESS) { | ||||
3375 | |||||
3376 | /* There is another command to * | ||||
3377 | * execute, so let's do that. */ | ||||
3378 | |||||
3379 | log_unit_debug(u, "Running next control command for state %s.", service_state_to_string(s->state))({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 3379, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Running next control command for state %s.", service_state_to_string (s->state)) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 3379, __func__, "Running next control command for state %s." , service_state_to_string(s->state)); }); | ||||
3380 | service_run_next_control(s); | ||||
3381 | |||||
3382 | } else { | ||||
3383 | /* No further commands for this step, so let's | ||||
3384 | * figure out what to do next */ | ||||
3385 | |||||
3386 | s->control_command = NULL((void*)0); | ||||
3387 | s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; | ||||
3388 | |||||
3389 | log_unit_debug(u, "Got final SIGCHLD for state %s.", service_state_to_string(s->state))({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 3389, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Got final SIGCHLD for state %s.", service_state_to_string( s->state)) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 3389, __func__, "Got final SIGCHLD for state %s." , service_state_to_string(s->state)); }); | ||||
3390 | |||||
3391 | switch (s->state) { | ||||
3392 | |||||
3393 | case SERVICE_CONDITION: | ||||
3394 | if (f == SERVICE_SUCCESS) | ||||
3395 | service_enter_start_pre(s); | ||||
3396 | else | ||||
3397 | service_enter_signal(s, SERVICE_STOP_SIGTERM, f); | ||||
3398 | break; | ||||
3399 | |||||
3400 | case SERVICE_START_PRE: | ||||
3401 | if (f == SERVICE_SUCCESS) | ||||
3402 | service_enter_start(s); | ||||
3403 | else | ||||
3404 | service_enter_signal(s, SERVICE_STOP_SIGTERM, f); | ||||
3405 | break; | ||||
3406 | |||||
3407 | case SERVICE_START: | ||||
3408 | if (s->type != SERVICE_FORKING) | ||||
3409 | /* Maybe spurious event due to a reload that changed the type? */ | ||||
3410 | break; | ||||
3411 | |||||
3412 | if (f != SERVICE_SUCCESS) { | ||||
3413 | service_enter_signal(s, SERVICE_STOP_SIGTERM, f); | ||||
3414 | break; | ||||
3415 | } | ||||
3416 | |||||
3417 | if (s->pid_file) { | ||||
3418 | bool_Bool has_start_post; | ||||
3419 | int r; | ||||
3420 | |||||
3421 | /* Let's try to load the pid file here if we can. | ||||
3422 | * The PID file might actually be created by a START_POST | ||||
3423 | * script. In that case don't worry if the loading fails. */ | ||||
3424 | |||||
3425 | has_start_post = s->exec_command[SERVICE_EXEC_START_POST]; | ||||
3426 | r = service_load_pid_file(s, !has_start_post); | ||||
3427 | if (!has_start_post && r < 0) { | ||||
3428 | r = service_demand_pid_file(s); | ||||
3429 | if (r < 0 || cgroup_good(s) == 0) | ||||
3430 | service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_PROTOCOL); | ||||
3431 | break; | ||||
3432 | } | ||||
3433 | } else | ||||
3434 | service_search_main_pid(s); | ||||
3435 | |||||
3436 | service_enter_start_post(s); | ||||
3437 | break; | ||||
3438 | |||||
3439 | case SERVICE_START_POST: | ||||
3440 | if (f != SERVICE_SUCCESS) { | ||||
3441 | service_enter_signal(s, SERVICE_STOP_SIGTERM, f); | ||||
3442 | break; | ||||
3443 | } | ||||
3444 | |||||
3445 | if (s->pid_file) { | ||||
3446 | int r; | ||||
3447 | |||||
3448 | r = service_load_pid_file(s, true1); | ||||
3449 | if (r < 0) { | ||||
3450 | r = service_demand_pid_file(s); | ||||
3451 | if (r < 0 || cgroup_good(s) == 0) | ||||
3452 | service_enter_stop(s, SERVICE_FAILURE_PROTOCOL); | ||||
3453 | break; | ||||
3454 | } | ||||
3455 | } else | ||||
3456 | service_search_main_pid(s); | ||||
3457 | |||||
3458 | service_enter_running(s, SERVICE_SUCCESS); | ||||
3459 | break; | ||||
3460 | |||||
3461 | case SERVICE_RELOAD: | ||||
3462 | if (f == SERVICE_SUCCESS) | ||||
3463 | if (service_load_pid_file(s, true1) < 0) | ||||
3464 | service_search_main_pid(s); | ||||
3465 | |||||
3466 | s->reload_result = f; | ||||
3467 | service_enter_running(s, SERVICE_SUCCESS); | ||||
3468 | break; | ||||
3469 | |||||
3470 | case SERVICE_STOP: | ||||
3471 | service_enter_signal(s, SERVICE_STOP_SIGTERM, f); | ||||
3472 | break; | ||||
3473 | |||||
3474 | case SERVICE_STOP_SIGABRT: | ||||
3475 | case SERVICE_STOP_SIGTERM: | ||||
3476 | case SERVICE_STOP_SIGKILL: | ||||
3477 | if (main_pid_good(s) <= 0) | ||||
3478 | service_enter_stop_post(s, f); | ||||
3479 | |||||
3480 | /* If there is still a service process around, wait until | ||||
3481 | * that one quit, too */ | ||||
3482 | break; | ||||
3483 | |||||
3484 | case SERVICE_STOP_POST: | ||||
3485 | if (main_pid_good(s) <= 0) | ||||
3486 | service_enter_signal(s, SERVICE_FINAL_SIGTERM, f); | ||||
3487 | break; | ||||
3488 | |||||
3489 | case SERVICE_FINAL_SIGTERM: | ||||
3490 | case SERVICE_FINAL_SIGKILL: | ||||
3491 | if (main_pid_good(s) <= 0) | ||||
3492 | service_enter_dead(s, f, true1); | ||||
3493 | break; | ||||
3494 | |||||
3495 | default: | ||||
3496 | assert_not_reached("Uh, control process died at wrong time.")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Uh, control process died at wrong time."), "../src/core/service.c" , 3496, __PRETTY_FUNCTION__); } while (0); | ||||
3497 | } | ||||
3498 | } | ||||
3499 | } else /* Neither control nor main PID? If so, don't notify about anything */ | ||||
3500 | notify_dbus = false0; | ||||
3501 | |||||
3502 | /* Notify clients about changed exit status */ | ||||
3503 | if (notify_dbus) | ||||
3504 | unit_add_to_dbus_queue(u); | ||||
3505 | |||||
3506 | /* We watch the main/control process otherwise we can't retrieve the unit they | ||||
3507 | * belong to with cgroupv1. But if they are not our direct child, we won't get a | ||||
3508 | * SIGCHLD for them. Therefore we need to look for others to watch so we can | ||||
3509 | * detect when the cgroup becomes empty. Note that the control process is always | ||||
3510 | * our child so it's pointless to watch all other processes. */ | ||||
3511 | if (!control_pid_good(s)) | ||||
3512 | if (!s->main_pid_known || s->main_pid_alien) | ||||
3513 | (void) unit_enqueue_rewatch_pids(u); | ||||
3514 | } | ||||
3515 | |||||
3516 | static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) { | ||||
3517 | Service *s = SERVICE(userdata); | ||||
3518 | |||||
3519 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 3519, __PRETTY_FUNCTION__ ); } while (0); | ||||
3520 | assert(source == s->timer_event_source)do { if ((__builtin_expect(!!(!(source == s->timer_event_source )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("source == s->timer_event_source" ), "../src/core/service.c", 3520, __PRETTY_FUNCTION__); } while (0); | ||||
3521 | |||||
3522 | switch (s->state) { | ||||
3523 | |||||
3524 | case SERVICE_CONDITION: | ||||
3525 | case SERVICE_START_PRE: | ||||
3526 | case SERVICE_START: | ||||
3527 | log_unit_warning(UNIT(s), "%s operation timed out. Terminating.", service_state_to_string(s->state))({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3527, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "%s operation timed out. Terminating." , service_state_to_string(s->state)) : log_internal_realm( ((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/service.c" , 3527, __func__, "%s operation timed out. Terminating.", service_state_to_string (s->state)); }); | ||||
3528 | service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT); | ||||
3529 | break; | ||||
3530 | |||||
3531 | case SERVICE_START_POST: | ||||
3532 | log_unit_warning(UNIT(s), "Start-post operation timed out. Stopping.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3532, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Start-post operation timed out. Stopping." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 3532, __func__, "Start-post operation timed out. Stopping." ); }); | ||||
3533 | service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT); | ||||
3534 | break; | ||||
3535 | |||||
3536 | case SERVICE_RUNNING: | ||||
3537 | log_unit_warning(UNIT(s), "Service reached runtime time limit. Stopping.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3537, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service reached runtime time limit. Stopping." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 3537, __func__, "Service reached runtime time limit. Stopping." ); }); | ||||
3538 | service_enter_stop(s, SERVICE_FAILURE_TIMEOUT); | ||||
3539 | break; | ||||
3540 | |||||
3541 | case SERVICE_RELOAD: | ||||
3542 | log_unit_warning(UNIT(s), "Reload operation timed out. Killing reload process.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3542, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Reload operation timed out. Killing reload process." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 3542, __func__, "Reload operation timed out. Killing reload process." ); }); | ||||
3543 | service_kill_control_process(s); | ||||
3544 | s->reload_result = SERVICE_FAILURE_TIMEOUT; | ||||
3545 | service_enter_running(s, SERVICE_SUCCESS); | ||||
3546 | break; | ||||
3547 | |||||
3548 | case SERVICE_STOP: | ||||
3549 | log_unit_warning(UNIT(s), "Stopping timed out. Terminating.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3549, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Stopping timed out. Terminating." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 3549, __func__, "Stopping timed out. Terminating." ); }); | ||||
3550 | service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT); | ||||
3551 | break; | ||||
3552 | |||||
3553 | case SERVICE_STOP_SIGABRT: | ||||
3554 | log_unit_warning(UNIT(s), "State 'stop-sigabrt' timed out. Terminating.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3554, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "State 'stop-sigabrt' timed out. Terminating." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 3554, __func__, "State 'stop-sigabrt' timed out. Terminating." ); }); | ||||
3555 | service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_TIMEOUT); | ||||
3556 | break; | ||||
3557 | |||||
3558 | case SERVICE_STOP_SIGTERM: | ||||
3559 | if (s->kill_context.send_sigkill) { | ||||
3560 | log_unit_warning(UNIT(s), "State 'stop-sigterm' timed out. Killing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3560, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "State 'stop-sigterm' timed out. Killing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 3560, __func__, "State 'stop-sigterm' timed out. Killing." ); }); | ||||
3561 | service_enter_signal(s, SERVICE_STOP_SIGKILL, SERVICE_FAILURE_TIMEOUT); | ||||
3562 | } else { | ||||
3563 | log_unit_warning(UNIT(s), "State 'stop-sigterm' timed out. Skipping SIGKILL.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3563, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "State 'stop-sigterm' timed out. Skipping SIGKILL." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 3563, __func__, "State 'stop-sigterm' timed out. Skipping SIGKILL." ); }); | ||||
3564 | service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT); | ||||
3565 | } | ||||
3566 | |||||
3567 | break; | ||||
3568 | |||||
3569 | case SERVICE_STOP_SIGKILL: | ||||
3570 | /* Uh, we sent a SIGKILL and it is still not gone? | ||||
3571 | * Must be something we cannot kill, so let's just be | ||||
3572 | * weirded out and continue */ | ||||
3573 | |||||
3574 | log_unit_warning(UNIT(s), "Processes still around after SIGKILL. Ignoring.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3574, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Processes still around after SIGKILL. Ignoring." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 3574, __func__, "Processes still around after SIGKILL. Ignoring." ); }); | ||||
3575 | service_enter_stop_post(s, SERVICE_FAILURE_TIMEOUT); | ||||
3576 | break; | ||||
3577 | |||||
3578 | case SERVICE_STOP_POST: | ||||
3579 | log_unit_warning(UNIT(s), "State 'stop-post' timed out. Terminating.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3579, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "State 'stop-post' timed out. Terminating." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 3579, __func__, "State 'stop-post' timed out. Terminating." ); }); | ||||
3580 | service_enter_signal(s, SERVICE_FINAL_SIGTERM, SERVICE_FAILURE_TIMEOUT); | ||||
3581 | break; | ||||
3582 | |||||
3583 | case SERVICE_FINAL_SIGTERM: | ||||
3584 | if (s->kill_context.send_sigkill) { | ||||
3585 | log_unit_warning(UNIT(s), "State 'stop-final-sigterm' timed out. Killing.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3585, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "State 'stop-final-sigterm' timed out. Killing." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 3585, __func__, "State 'stop-final-sigterm' timed out. Killing." ); }); | ||||
3586 | service_enter_signal(s, SERVICE_FINAL_SIGKILL, SERVICE_FAILURE_TIMEOUT); | ||||
3587 | } else { | ||||
3588 | log_unit_warning(UNIT(s), "State 'stop-final-sigterm' timed out. Skipping SIGKILL. Entering failed mode.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3588, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "State 'stop-final-sigterm' timed out. Skipping SIGKILL. Entering failed mode." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 3588, __func__, "State 'stop-final-sigterm' timed out. Skipping SIGKILL. Entering failed mode." ); }); | ||||
3589 | service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, false0); | ||||
3590 | } | ||||
3591 | |||||
3592 | break; | ||||
3593 | |||||
3594 | case SERVICE_FINAL_SIGKILL: | ||||
3595 | log_unit_warning(UNIT(s), "Processes still around after final SIGKILL. Entering failed mode.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3595, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Processes still around after final SIGKILL. Entering failed mode." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 3595, __func__, "Processes still around after final SIGKILL. Entering failed mode." ); }); | ||||
3596 | service_enter_dead(s, SERVICE_FAILURE_TIMEOUT, true1); | ||||
3597 | break; | ||||
3598 | |||||
3599 | case SERVICE_AUTO_RESTART: | ||||
3600 | if (s->restart_usec > 0) { | ||||
3601 | char buf_restart[FORMAT_TIMESPAN_MAX64]; | ||||
3602 | log_unit_info(UNIT(s),({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (6, 0, "../src/core/service.c", 3604, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service RestartSec=%s expired, scheduling restart." , format_timespan(buf_restart, sizeof buf_restart, s->restart_usec , ((usec_t) 1000000ULL))) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((6))), 0, "../src/core/service.c", 3604, __func__ , "Service RestartSec=%s expired, scheduling restart.", format_timespan (buf_restart, sizeof buf_restart, s->restart_usec, ((usec_t ) 1000000ULL))); }) | ||||
3603 | "Service RestartSec=%s expired, scheduling restart.",({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (6, 0, "../src/core/service.c", 3604, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service RestartSec=%s expired, scheduling restart." , format_timespan(buf_restart, sizeof buf_restart, s->restart_usec , ((usec_t) 1000000ULL))) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((6))), 0, "../src/core/service.c", 3604, __func__ , "Service RestartSec=%s expired, scheduling restart.", format_timespan (buf_restart, sizeof buf_restart, s->restart_usec, ((usec_t ) 1000000ULL))); }) | ||||
3604 | format_timespan(buf_restart, sizeof buf_restart, s->restart_usec, USEC_PER_SEC))({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (6, 0, "../src/core/service.c", 3604, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service RestartSec=%s expired, scheduling restart." , format_timespan(buf_restart, sizeof buf_restart, s->restart_usec , ((usec_t) 1000000ULL))) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((6))), 0, "../src/core/service.c", 3604, __func__ , "Service RestartSec=%s expired, scheduling restart.", format_timespan (buf_restart, sizeof buf_restart, s->restart_usec, ((usec_t ) 1000000ULL))); }); | ||||
3605 | } else | ||||
3606 | log_unit_info(UNIT(s),({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (6, 0, "../src/core/service.c", 3607, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service has no hold-off time (RestartSec=0), scheduling restart." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((6 ))), 0, "../src/core/service.c", 3607, __func__, "Service has no hold-off time (RestartSec=0), scheduling restart." ); }) | ||||
3607 | "Service has no hold-off time (RestartSec=0), scheduling restart.")({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (6, 0, "../src/core/service.c", 3607, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Service has no hold-off time (RestartSec=0), scheduling restart." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((6 ))), 0, "../src/core/service.c", 3607, __func__, "Service has no hold-off time (RestartSec=0), scheduling restart." ); }); | ||||
3608 | |||||
3609 | service_enter_restart(s); | ||||
3610 | break; | ||||
3611 | |||||
3612 | default: | ||||
3613 | assert_not_reached("Timeout at wrong time.")do { log_assert_failed_unreachable_realm(LOG_REALM_SYSTEMD, ( "Timeout at wrong time."), "../src/core/service.c", 3613, __PRETTY_FUNCTION__ ); } while (0); | ||||
3614 | } | ||||
3615 | |||||
3616 | return 0; | ||||
3617 | } | ||||
3618 | |||||
3619 | static int service_dispatch_watchdog(sd_event_source *source, usec_t usec, void *userdata) { | ||||
3620 | Service *s = SERVICE(userdata); | ||||
3621 | char t[FORMAT_TIMESPAN_MAX64]; | ||||
3622 | usec_t watchdog_usec; | ||||
3623 | |||||
3624 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 3624, __PRETTY_FUNCTION__ ); } while (0); | ||||
3625 | assert(source == s->watchdog_event_source)do { if ((__builtin_expect(!!(!(source == s->watchdog_event_source )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("source == s->watchdog_event_source" ), "../src/core/service.c", 3625, __PRETTY_FUNCTION__); } while (0); | ||||
3626 | |||||
3627 | watchdog_usec = service_get_watchdog_usec(s); | ||||
3628 | |||||
3629 | if (UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->manager->service_watchdogs) { | ||||
3630 | log_unit_error(UNIT(s), "Watchdog timeout (limit %s)!",({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/service.c", 3631, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Watchdog timeout (limit %s)!" , format_timespan(t, sizeof(t), watchdog_usec, 1)) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((3))), 0, "../src/core/service.c" , 3631, __func__, "Watchdog timeout (limit %s)!", format_timespan (t, sizeof(t), watchdog_usec, 1)); }) | ||||
3631 | format_timespan(t, sizeof(t), watchdog_usec, 1))({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (3, 0, "../src/core/service.c", 3631, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Watchdog timeout (limit %s)!" , format_timespan(t, sizeof(t), watchdog_usec, 1)) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((3))), 0, "../src/core/service.c" , 3631, __func__, "Watchdog timeout (limit %s)!", format_timespan (t, sizeof(t), watchdog_usec, 1)); }); | ||||
3632 | |||||
3633 | service_enter_signal(s, SERVICE_STOP_SIGABRT, SERVICE_FAILURE_WATCHDOG); | ||||
3634 | } else | ||||
3635 | log_unit_warning(UNIT(s), "Watchdog disabled! Ignoring watchdog timeout (limit %s)!",({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3636, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Watchdog disabled! Ignoring watchdog timeout (limit %s)!" , format_timespan(t, sizeof(t), watchdog_usec, 1)) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/service.c" , 3636, __func__, "Watchdog disabled! Ignoring watchdog timeout (limit %s)!" , format_timespan(t, sizeof(t), watchdog_usec, 1)); }) | ||||
3636 | format_timespan(t, sizeof(t), watchdog_usec, 1))({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3636, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Watchdog disabled! Ignoring watchdog timeout (limit %s)!" , format_timespan(t, sizeof(t), watchdog_usec, 1)) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/service.c" , 3636, __func__, "Watchdog disabled! Ignoring watchdog timeout (limit %s)!" , format_timespan(t, sizeof(t), watchdog_usec, 1)); }); | ||||
3637 | |||||
3638 | return 0; | ||||
3639 | } | ||||
3640 | |||||
3641 | static bool_Bool service_notify_message_authorized(Service *s, pid_t pid, char **tags, FDSet *fds) { | ||||
3642 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 3642, __PRETTY_FUNCTION__ ); } while (0); | ||||
3643 | |||||
3644 | if (s->notify_access == NOTIFY_NONE) { | ||||
3645 | log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception is disabled.", pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3645, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got notification message from PID " "%" "i"", but reception is disabled.", pid) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/service.c" , 3645, __func__, "Got notification message from PID ""%" "i" ", but reception is disabled.", pid); }); | ||||
3646 | return false0; | ||||
3647 | } | ||||
3648 | |||||
3649 | if (s->notify_access == NOTIFY_MAIN && pid != s->main_pid) { | ||||
3650 | if (s->main_pid != 0) | ||||
3651 | log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT, pid, s->main_pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3651, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got notification message from PID " "%" "i"", but reception only permitted for main PID ""%" "i", pid, s->main_pid) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), 0, "../src/core/service.c", 3651, __func__ , "Got notification message from PID ""%" "i"", but reception only permitted for main PID " "%" "i", pid, s->main_pid); }); | ||||
3652 | else | ||||
3653 | log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for main PID which is currently not known", pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3653, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got notification message from PID " "%" "i"", but reception only permitted for main PID which is currently not known" , pid) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/service.c", 3653, __func__, "Got notification message from PID " "%" "i"", but reception only permitted for main PID which is currently not known" , pid); }); | ||||
3654 | |||||
3655 | return false0; | ||||
3656 | } | ||||
3657 | |||||
3658 | if (s->notify_access == NOTIFY_EXEC && pid != s->main_pid && pid != s->control_pid) { | ||||
3659 | if (s->main_pid != 0 && s->control_pid != 0) | ||||
3660 | log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT" and control PID "PID_FMT,({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3661, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got notification message from PID " "%" "i"", but reception only permitted for main PID ""%" "i"" and control PID " "%" "i", pid, s->main_pid, s->control_pid) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/service.c" , 3661, __func__, "Got notification message from PID ""%" "i" ", but reception only permitted for main PID ""%" "i"" and control PID " "%" "i", pid, s->main_pid, s->control_pid); }) | ||||
3661 | pid, s->main_pid, s->control_pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3661, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got notification message from PID " "%" "i"", but reception only permitted for main PID ""%" "i"" and control PID " "%" "i", pid, s->main_pid, s->control_pid) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/service.c" , 3661, __func__, "Got notification message from PID ""%" "i" ", but reception only permitted for main PID ""%" "i"" and control PID " "%" "i", pid, s->main_pid, s->control_pid); }); | ||||
3662 | else if (s->main_pid != 0) | ||||
3663 | log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT, pid, s->main_pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3663, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got notification message from PID " "%" "i"", but reception only permitted for main PID ""%" "i", pid, s->main_pid) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), 0, "../src/core/service.c", 3663, __func__ , "Got notification message from PID ""%" "i"", but reception only permitted for main PID " "%" "i", pid, s->main_pid); }); | ||||
3664 | else if (s->control_pid != 0) | ||||
3665 | log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for control PID "PID_FMT, pid, s->control_pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3665, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got notification message from PID " "%" "i"", but reception only permitted for control PID ""%" "i" , pid, s->control_pid) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((4))), 0, "../src/core/service.c", 3665, __func__ , "Got notification message from PID ""%" "i"", but reception only permitted for control PID " "%" "i", pid, s->control_pid); }); | ||||
3666 | else | ||||
3667 | log_unit_warning(UNIT(s), "Got notification message from PID "PID_FMT", but reception only permitted for main PID and control PID which are currently not known", pid)({ const Unit *_u = (({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })); _u ? log_object_internal (4, 0, "../src/core/service.c", 3667, __func__, _u->manager ->unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Got notification message from PID " "%" "i"", but reception only permitted for main PID and control PID which are currently not known" , pid) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/service.c", 3667, __func__, "Got notification message from PID " "%" "i"", but reception only permitted for main PID and control PID which are currently not known" , pid); }); | ||||
3668 | |||||
3669 | return false0; | ||||
3670 | } | ||||
3671 | |||||
3672 | return true1; | ||||
3673 | } | ||||
3674 | |||||
3675 | static void service_notify_message( | ||||
3676 | Unit *u, | ||||
3677 | const struct ucred *ucred, | ||||
3678 | char **tags, | ||||
3679 | FDSet *fds) { | ||||
3680 | |||||
3681 | Service *s = SERVICE(u); | ||||
3682 | bool_Bool notify_dbus = false0; | ||||
3683 | const char *e; | ||||
3684 | char **i; | ||||
3685 | int r; | ||||
3686 | |||||
3687 | assert(u)do { if ((__builtin_expect(!!(!(u)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("u"), "../src/core/service.c", 3687, __PRETTY_FUNCTION__ ); } while (0); | ||||
3688 | assert(ucred)do { if ((__builtin_expect(!!(!(ucred)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("ucred"), "../src/core/service.c", 3688, __PRETTY_FUNCTION__); } while (0); | ||||
3689 | |||||
3690 | if (!service_notify_message_authorized(SERVICE(u), ucred->pid, tags, fds)) | ||||
3691 | return; | ||||
3692 | |||||
3693 | if (DEBUG_LOGGING(__builtin_expect(!!(log_get_max_level_realm(LOG_REALM_SYSTEMD ) >= 7),0))) { | ||||
3694 | _cleanup_free___attribute__((cleanup(freep))) char *cc = NULL((void*)0); | ||||
3695 | |||||
3696 | cc = strv_join(tags, ", "); | ||||
3697 | log_unit_debug(u, "Got notification message from PID "PID_FMT" (%s)", ucred->pid, isempty(cc) ? "n/a" : cc)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 3697, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Got notification message from PID ""%" "i"" (%s)", ucred-> pid, isempty(cc) ? "n/a" : cc) : log_internal_realm(((LOG_REALM_SYSTEMD ) << 10 | ((7))), 0, "../src/core/service.c", 3697, __func__ , "Got notification message from PID ""%" "i"" (%s)", ucred-> pid, isempty(cc) ? "n/a" : cc); }); | ||||
3698 | } | ||||
3699 | |||||
3700 | /* Interpret MAINPID= */ | ||||
3701 | e = strv_find_startswith(tags, "MAINPID="); | ||||
3702 | if (e && IN_SET(s->state, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD})/sizeof(int)]; switch(s->state) { case SERVICE_START : case SERVICE_START_POST: case SERVICE_RUNNING: case SERVICE_RELOAD : _found = 1; break; default: break; } _found; })) { | ||||
3703 | pid_t new_main_pid; | ||||
3704 | |||||
3705 | if (parse_pid(e, &new_main_pid) < 0) | ||||
3706 | log_unit_warning(u, "Failed to parse MAINPID= field in notification message, ignoring: %s", e)({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/service.c" , 3706, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse MAINPID= field in notification message, ignoring: %s" , e) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ( (4))), 0, "../src/core/service.c", 3706, __func__, "Failed to parse MAINPID= field in notification message, ignoring: %s" , e); }); | ||||
3707 | else if (!s->main_pid_known || new_main_pid != s->main_pid) { | ||||
3708 | |||||
3709 | r = service_is_suitable_main_pid(s, new_main_pid, LOG_WARNING4); | ||||
3710 | if (r == 0) { | ||||
3711 | /* The new main PID is a bit suspicous, which is OK if the sender is privileged. */ | ||||
3712 | |||||
3713 | if (ucred->uid == 0) { | ||||
3714 | log_unit_debug(u, "New main PID "PID_FMT" does not belong to service, but we'll accept it as the request to change it came from a privileged process.", new_main_pid)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 3714, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "New main PID ""%" "i"" does not belong to service, but we'll accept it as the request to change it came from a privileged process." , new_main_pid) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 3714, __func__, "New main PID " "%" "i"" does not belong to service, but we'll accept it as the request to change it came from a privileged process." , new_main_pid); }); | ||||
3715 | r = 1; | ||||
3716 | } else | ||||
3717 | log_unit_debug(u, "New main PID "PID_FMT" does not belong to service, refusing.", new_main_pid)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 3717, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "New main PID ""%" "i"" does not belong to service, refusing." , new_main_pid) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 3717, __func__, "New main PID " "%" "i"" does not belong to service, refusing.", new_main_pid ); }); | ||||
3718 | } | ||||
3719 | if (r > 0) { | ||||
3720 | service_set_main_pid(s, new_main_pid); | ||||
3721 | unit_watch_pid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), new_main_pid, false0); | ||||
3722 | notify_dbus = true1; | ||||
3723 | } | ||||
3724 | } | ||||
3725 | } | ||||
3726 | |||||
3727 | /* Interpret READY=/STOPPING=/RELOADING=. Last one wins. */ | ||||
3728 | STRV_FOREACH_BACKWARDS(i, tags)for (i = ({ char **_l = tags; _l ? _l + strv_length(_l) - 1U : ((void*)0); }); (tags) && ((i) >= (tags)); (i)--) { | ||||
3729 | |||||
3730 | if (streq(*i, "READY=1")(strcmp((*i),("READY=1")) == 0)) { | ||||
3731 | s->notify_state = NOTIFY_READY; | ||||
3732 | |||||
3733 | /* Type=notify services inform us about completed | ||||
3734 | * initialization with READY=1 */ | ||||
3735 | if (s->type == SERVICE_NOTIFY && s->state == SERVICE_START) | ||||
3736 | service_enter_start_post(s); | ||||
3737 | |||||
3738 | /* Sending READY=1 while we are reloading informs us | ||||
3739 | * that the reloading is complete */ | ||||
3740 | if (s->state == SERVICE_RELOAD && s->control_pid == 0) | ||||
3741 | service_enter_running(s, SERVICE_SUCCESS); | ||||
3742 | |||||
3743 | notify_dbus = true1; | ||||
3744 | break; | ||||
3745 | |||||
3746 | } else if (streq(*i, "RELOADING=1")(strcmp((*i),("RELOADING=1")) == 0)) { | ||||
3747 | s->notify_state = NOTIFY_RELOADING; | ||||
3748 | |||||
3749 | if (s->state == SERVICE_RUNNING) | ||||
3750 | service_enter_reload_by_notify(s); | ||||
3751 | |||||
3752 | notify_dbus = true1; | ||||
3753 | break; | ||||
3754 | |||||
3755 | } else if (streq(*i, "STOPPING=1")(strcmp((*i),("STOPPING=1")) == 0)) { | ||||
3756 | s->notify_state = NOTIFY_STOPPING; | ||||
3757 | |||||
3758 | if (s->state == SERVICE_RUNNING) | ||||
3759 | service_enter_stop_by_notify(s); | ||||
3760 | |||||
3761 | notify_dbus = true1; | ||||
3762 | break; | ||||
3763 | } | ||||
3764 | } | ||||
3765 | |||||
3766 | /* Interpret STATUS= */ | ||||
3767 | e = strv_find_startswith(tags, "STATUS="); | ||||
3768 | if (e) { | ||||
3769 | _cleanup_free___attribute__((cleanup(freep))) char *t = NULL((void*)0); | ||||
3770 | |||||
3771 | if (!isempty(e)) { | ||||
3772 | /* Note that this size limit check is mostly paranoia: since the datagram size we are willing | ||||
3773 | * to process is already limited to NOTIFY_BUFFER_MAX, this limit here should never be hit. */ | ||||
3774 | if (strlen(e) > STATUS_TEXT_MAX(16U*1024U)) | ||||
3775 | log_unit_warning(u, "Status message overly long (%zu > %u), ignoring.", strlen(e), STATUS_TEXT_MAX)({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/service.c" , 3775, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Status message overly long (%zu > %u), ignoring.", strlen (e), (16U*1024U)) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/service.c", 3775, __func__, "Status message overly long (%zu > %u), ignoring." , strlen(e), (16U*1024U)); }); | ||||
3776 | else if (!utf8_is_valid(e)) | ||||
3777 | log_unit_warning(u, "Status message in notification message is not UTF-8 clean, ignoring.")({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/service.c" , 3777, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Status message in notification message is not UTF-8 clean, ignoring." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 3777, __func__, "Status message in notification message is not UTF-8 clean, ignoring." ); }); | ||||
3778 | else { | ||||
3779 | t = strdup(e); | ||||
3780 | if (!t) | ||||
3781 | log_oom()log_oom_internal(LOG_REALM_SYSTEMD, "../src/core/service.c", 3781 , __func__); | ||||
3782 | } | ||||
3783 | } | ||||
3784 | |||||
3785 | if (!streq_ptr(s->status_text, t)) { | ||||
3786 | free_and_replace(s->status_text, t)({ free(s->status_text); (s->status_text) = (t); (t) = ( (void*)0); 0; }); | ||||
3787 | notify_dbus = true1; | ||||
3788 | } | ||||
3789 | } | ||||
3790 | |||||
3791 | /* Interpret ERRNO= */ | ||||
3792 | e = strv_find_startswith(tags, "ERRNO="); | ||||
3793 | if (e) { | ||||
3794 | int status_errno; | ||||
3795 | |||||
3796 | status_errno = parse_errno(e); | ||||
3797 | if (status_errno < 0) | ||||
3798 | log_unit_warning_errno(u, status_errno,({ const Unit *_u = (u); _u ? log_object_internal(4, status_errno , "../src/core/service.c", 3799, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to parse ERRNO= field in notification message: %s" , e) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ( (4))), status_errno, "../src/core/service.c", 3799, __func__, "Failed to parse ERRNO= field in notification message: %s", e ); }) | ||||
3799 | "Failed to parse ERRNO= field in notification message: %s", e)({ const Unit *_u = (u); _u ? log_object_internal(4, status_errno , "../src/core/service.c", 3799, __func__, _u->manager-> unit_log_field, _u->id, _u->manager->invocation_log_field , _u->invocation_id_string, "Failed to parse ERRNO= field in notification message: %s" , e) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ( (4))), status_errno, "../src/core/service.c", 3799, __func__, "Failed to parse ERRNO= field in notification message: %s", e ); }); | ||||
3800 | else if (s->status_errno != status_errno) { | ||||
3801 | s->status_errno = status_errno; | ||||
3802 | notify_dbus = true1; | ||||
3803 | } | ||||
3804 | } | ||||
3805 | |||||
3806 | /* Interpret EXTEND_TIMEOUT= */ | ||||
3807 | e = strv_find_startswith(tags, "EXTEND_TIMEOUT_USEC="); | ||||
3808 | if (e) { | ||||
3809 | usec_t extend_timeout_usec; | ||||
3810 | if (safe_atou64(e, &extend_timeout_usec) < 0) | ||||
3811 | log_unit_warning(u, "Failed to parse EXTEND_TIMEOUT_USEC=%s", e)({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/service.c" , 3811, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse EXTEND_TIMEOUT_USEC=%s", e) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/service.c" , 3811, __func__, "Failed to parse EXTEND_TIMEOUT_USEC=%s", e ); }); | ||||
3812 | else | ||||
3813 | service_extend_timeout(s, extend_timeout_usec); | ||||
3814 | } | ||||
3815 | |||||
3816 | /* Interpret WATCHDOG= */ | ||||
3817 | if (strv_find(tags, "WATCHDOG=1")) | ||||
3818 | service_reset_watchdog(s); | ||||
3819 | |||||
3820 | e = strv_find_startswith(tags, "WATCHDOG_USEC="); | ||||
3821 | if (e) { | ||||
3822 | usec_t watchdog_override_usec; | ||||
3823 | if (safe_atou64(e, &watchdog_override_usec) < 0) | ||||
3824 | log_unit_warning(u, "Failed to parse WATCHDOG_USEC=%s", e)({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/service.c" , 3824, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Failed to parse WATCHDOG_USEC=%s", e) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/service.c" , 3824, __func__, "Failed to parse WATCHDOG_USEC=%s", e); }); | ||||
3825 | else | ||||
3826 | service_reset_watchdog_timeout(s, watchdog_override_usec); | ||||
3827 | } | ||||
3828 | |||||
3829 | /* Process FD store messages. Either FDSTOREREMOVE=1 for removal, or FDSTORE=1 for addition. In both cases, | ||||
3830 | * process FDNAME= for picking the file descriptor name to use. Note that FDNAME= is required when removing | ||||
3831 | * fds, but optional when pushing in new fds, for compatibility reasons. */ | ||||
3832 | if (strv_find(tags, "FDSTOREREMOVE=1")) { | ||||
3833 | const char *name; | ||||
3834 | |||||
3835 | name = strv_find_startswith(tags, "FDNAME="); | ||||
3836 | if (!name || !fdname_is_valid(name)) | ||||
3837 | log_unit_warning(u, "FDSTOREREMOVE=1 requested, but no valid file descriptor name passed, ignoring.")({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/service.c" , 3837, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "FDSTOREREMOVE=1 requested, but no valid file descriptor name passed, ignoring." ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((4 ))), 0, "../src/core/service.c", 3837, __func__, "FDSTOREREMOVE=1 requested, but no valid file descriptor name passed, ignoring." ); }); | ||||
3838 | else | ||||
3839 | service_remove_fd_store(s, name); | ||||
3840 | |||||
3841 | } else if (strv_find(tags, "FDSTORE=1")) { | ||||
3842 | const char *name; | ||||
3843 | |||||
3844 | name = strv_find_startswith(tags, "FDNAME="); | ||||
3845 | if (name && !fdname_is_valid(name)) { | ||||
3846 | log_unit_warning(u, "Passed FDNAME= name is invalid, ignoring.")({ const Unit *_u = (u); _u ? log_object_internal(4, 0, "../src/core/service.c" , 3846, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Passed FDNAME= name is invalid, ignoring.") : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((4))), 0, "../src/core/service.c" , 3846, __func__, "Passed FDNAME= name is invalid, ignoring." ); }); | ||||
3847 | name = NULL((void*)0); | ||||
3848 | } | ||||
3849 | |||||
3850 | (void) service_add_fd_store_set(s, fds, name); | ||||
3851 | } | ||||
3852 | |||||
3853 | /* Notify clients about changed status or main pid */ | ||||
3854 | if (notify_dbus) | ||||
3855 | unit_add_to_dbus_queue(u); | ||||
3856 | } | ||||
3857 | |||||
3858 | static int service_get_timeout(Unit *u, usec_t *timeout) { | ||||
3859 | Service *s = SERVICE(u); | ||||
3860 | uint64_t t; | ||||
3861 | int r; | ||||
3862 | |||||
3863 | if (!s->timer_event_source) | ||||
3864 | return 0; | ||||
3865 | |||||
3866 | r = sd_event_source_get_time(s->timer_event_source, &t); | ||||
3867 | if (r < 0) | ||||
3868 | return r; | ||||
3869 | if (t == USEC_INFINITY((usec_t) -1)) | ||||
3870 | return 0; | ||||
3871 | |||||
3872 | *timeout = t; | ||||
3873 | return 1; | ||||
3874 | } | ||||
3875 | |||||
3876 | static void service_bus_name_owner_change( | ||||
3877 | Unit *u, | ||||
3878 | const char *name, | ||||
3879 | const char *old_owner, | ||||
3880 | const char *new_owner) { | ||||
3881 | |||||
3882 | Service *s = SERVICE(u); | ||||
3883 | int r; | ||||
3884 | |||||
3885 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 3885, __PRETTY_FUNCTION__ ); } while (0); | ||||
3886 | assert(name)do { if ((__builtin_expect(!!(!(name)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("name"), "../src/core/service.c", 3886, __PRETTY_FUNCTION__ ); } while (0); | ||||
3887 | |||||
3888 | assert(streq(s->bus_name, name))do { if ((__builtin_expect(!!(!((strcmp((s->bus_name),(name )) == 0))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("streq(s->bus_name, name)" ), "../src/core/service.c", 3888, __PRETTY_FUNCTION__); } while (0); | ||||
3889 | assert(old_owner || new_owner)do { if ((__builtin_expect(!!(!(old_owner || new_owner)),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("old_owner || new_owner" ), "../src/core/service.c", 3889, __PRETTY_FUNCTION__); } while (0); | ||||
3890 | |||||
3891 | if (old_owner && new_owner) | ||||
3892 | log_unit_debug(u, "D-Bus name %s changed owner from %s to %s", name, old_owner, new_owner)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 3892, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "D-Bus name %s changed owner from %s to %s", name, old_owner , new_owner) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c", 3892, __func__, "D-Bus name %s changed owner from %s to %s" , name, old_owner, new_owner); }); | ||||
3893 | else if (old_owner) | ||||
3894 | log_unit_debug(u, "D-Bus name %s no longer registered by %s", name, old_owner)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 3894, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "D-Bus name %s no longer registered by %s", name, old_owner ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7 ))), 0, "../src/core/service.c", 3894, __func__, "D-Bus name %s no longer registered by %s" , name, old_owner); }); | ||||
3895 | else | ||||
3896 | log_unit_debug(u, "D-Bus name %s now registered by %s", name, new_owner)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 3896, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "D-Bus name %s now registered by %s", name, new_owner) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((7))), 0, "../src/core/service.c" , 3896, __func__, "D-Bus name %s now registered by %s", name, new_owner); }); | ||||
3897 | |||||
3898 | s->bus_name_good = !!new_owner; | ||||
3899 | |||||
3900 | /* Track the current owner, so we can reconstruct changes after a daemon reload */ | ||||
3901 | r = free_and_strdup(&s->bus_name_owner, new_owner); | ||||
3902 | if (r < 0) { | ||||
3903 | log_unit_error_errno(u, r, "Unable to set new bus name owner %s: %m", new_owner)({ const Unit *_u = (u); _u ? log_object_internal(3, r, "../src/core/service.c" , 3903, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "Unable to set new bus name owner %s: %m", new_owner) : log_internal_realm (((LOG_REALM_SYSTEMD) << 10 | ((3))), r, "../src/core/service.c" , 3903, __func__, "Unable to set new bus name owner %s: %m", new_owner ); }); | ||||
3904 | return; | ||||
3905 | } | ||||
3906 | |||||
3907 | if (s->type == SERVICE_DBUS) { | ||||
3908 | |||||
3909 | /* service_enter_running() will figure out what to | ||||
3910 | * do */ | ||||
3911 | if (s->state == SERVICE_RUNNING) | ||||
3912 | service_enter_running(s, SERVICE_SUCCESS); | ||||
3913 | else if (s->state == SERVICE_START && new_owner) | ||||
3914 | service_enter_start_post(s); | ||||
3915 | |||||
3916 | } else if (new_owner && | ||||
3917 | s->main_pid <= 0 && | ||||
3918 | IN_SET(s->state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD})/sizeof(int)]; switch(s->state) { case SERVICE_START : case SERVICE_START_POST: case SERVICE_RUNNING: case SERVICE_RELOAD : _found = 1; break; default: break; } _found; }) | ||||
3919 | SERVICE_START,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD})/sizeof(int)]; switch(s->state) { case SERVICE_START : case SERVICE_START_POST: case SERVICE_RUNNING: case SERVICE_RELOAD : _found = 1; break; default: break; } _found; }) | ||||
3920 | SERVICE_START_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD})/sizeof(int)]; switch(s->state) { case SERVICE_START : case SERVICE_START_POST: case SERVICE_RUNNING: case SERVICE_RELOAD : _found = 1; break; default: break; } _found; }) | ||||
3921 | SERVICE_RUNNING,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD})/sizeof(int)]; switch(s->state) { case SERVICE_START : case SERVICE_START_POST: case SERVICE_RUNNING: case SERVICE_RELOAD : _found = 1; break; default: break; } _found; }) | ||||
3922 | SERVICE_RELOAD)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING , SERVICE_RELOAD})/sizeof(int)]; switch(s->state) { case SERVICE_START : case SERVICE_START_POST: case SERVICE_RUNNING: case SERVICE_RELOAD : _found = 1; break; default: break; } _found; })) { | ||||
3923 | |||||
3924 | _cleanup_(sd_bus_creds_unrefp)__attribute__((cleanup(sd_bus_creds_unrefp))) sd_bus_creds *creds = NULL((void*)0); | ||||
3925 | pid_t pid; | ||||
3926 | |||||
3927 | /* Try to acquire PID from bus service */ | ||||
3928 | |||||
3929 | r = sd_bus_get_name_creds(u->manager->api_bus, name, SD_BUS_CREDS_PID, &creds); | ||||
3930 | if (r >= 0) | ||||
3931 | r = sd_bus_creds_get_pid(creds, &pid); | ||||
3932 | if (r >= 0) { | ||||
3933 | log_unit_debug(u, "D-Bus name %s is now owned by process " PID_FMT, name, pid)({ const Unit *_u = (u); _u ? log_object_internal(7, 0, "../src/core/service.c" , 3933, __func__, _u->manager->unit_log_field, _u->id , _u->manager->invocation_log_field, _u->invocation_id_string , "D-Bus name %s is now owned by process " "%" "i", name, pid ) : log_internal_realm(((LOG_REALM_SYSTEMD) << 10 | ((7 ))), 0, "../src/core/service.c", 3933, __func__, "D-Bus name %s is now owned by process " "%" "i", name, pid); }); | ||||
3934 | |||||
3935 | service_set_main_pid(s, pid); | ||||
3936 | unit_watch_pid(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), pid, false0); | ||||
3937 | } | ||||
3938 | } | ||||
3939 | } | ||||
3940 | |||||
3941 | int service_set_socket_fd(Service *s, int fd, Socket *sock, bool_Bool selinux_context_net) { | ||||
3942 | _cleanup_free___attribute__((cleanup(freep))) char *peer = NULL((void*)0); | ||||
3943 | int r; | ||||
3944 | |||||
3945 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 3945, __PRETTY_FUNCTION__ ); } while (0); | ||||
3946 | assert(fd >= 0)do { if ((__builtin_expect(!!(!(fd >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("fd >= 0"), "../src/core/service.c", 3946 , __PRETTY_FUNCTION__); } while (0); | ||||
3947 | |||||
3948 | /* This is called by the socket code when instantiating a new service for a stream socket and the socket needs | ||||
3949 | * to be configured. We take ownership of the passed fd on success. */ | ||||
3950 | |||||
3951 | if (UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->load_state != UNIT_LOADED) | ||||
3952 | return -EINVAL22; | ||||
3953 | |||||
3954 | if (s->socket_fd >= 0) | ||||
3955 | return -EBUSY16; | ||||
3956 | |||||
3957 | if (s->state != SERVICE_DEAD) | ||||
3958 | return -EAGAIN11; | ||||
3959 | |||||
3960 | if (getpeername_pretty(fd, true1, &peer) >= 0) { | ||||
3961 | |||||
3962 | if (UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; })->description) { | ||||
3963 | _cleanup_free___attribute__((cleanup(freep))) char *a; | ||||
3964 | |||||
3965 | a = strjoin(UNIT(s)->description, " (", peer, ")")strjoin_real((({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? & (_u_)->meta : ((void*)0); _w_; })->description), " (", peer , ")", ((void*)0)); | ||||
3966 | if (!a) | ||||
3967 | return -ENOMEM12; | ||||
3968 | |||||
3969 | r = unit_set_description(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), a); | ||||
3970 | } else | ||||
3971 | r = unit_set_description(UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), peer); | ||||
3972 | |||||
3973 | if (r < 0) | ||||
3974 | return r; | ||||
3975 | } | ||||
3976 | |||||
3977 | r = unit_add_two_dependencies(UNIT(sock)({ typeof(sock) _u_ = (sock); Unit *_w_ = _u_ ? &(_u_)-> meta : ((void*)0); _w_; }), UNIT_BEFORE, UNIT_TRIGGERS, UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), false0, UNIT_DEPENDENCY_IMPLICIT); | ||||
3978 | if (r < 0) | ||||
3979 | return r; | ||||
3980 | |||||
3981 | s->socket_fd = fd; | ||||
3982 | s->socket_fd_selinux_context_net = selinux_context_net; | ||||
3983 | |||||
3984 | unit_ref_set(&s->accept_socket, UNIT(s)({ typeof(s) _u_ = (s); Unit *_w_ = _u_ ? &(_u_)->meta : ((void*)0); _w_; }), UNIT(sock)({ typeof(sock) _u_ = (sock); Unit *_w_ = _u_ ? &(_u_)-> meta : ((void*)0); _w_; })); | ||||
3985 | return 0; | ||||
3986 | } | ||||
3987 | |||||
3988 | static void service_reset_failed(Unit *u) { | ||||
3989 | Service *s = SERVICE(u); | ||||
3990 | |||||
3991 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 3991, __PRETTY_FUNCTION__ ); } while (0); | ||||
3992 | |||||
3993 | if (s->state == SERVICE_FAILED) | ||||
3994 | service_set_state(s, SERVICE_DEAD); | ||||
3995 | |||||
3996 | s->result = SERVICE_SUCCESS; | ||||
3997 | s->reload_result = SERVICE_SUCCESS; | ||||
3998 | s->n_restarts = 0; | ||||
3999 | s->flush_n_restarts = false0; | ||||
4000 | } | ||||
4001 | |||||
4002 | static int service_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) { | ||||
4003 | Service *s = SERVICE(u); | ||||
4004 | |||||
4005 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 4005, __PRETTY_FUNCTION__ ); } while (0); | ||||
4006 | |||||
4007 | return unit_kill_common(u, who, signo, s->main_pid, s->control_pid, error); | ||||
4008 | } | ||||
4009 | |||||
4010 | static int service_main_pid(Unit *u) { | ||||
4011 | Service *s = SERVICE(u); | ||||
4012 | |||||
4013 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 4013, __PRETTY_FUNCTION__ ); } while (0); | ||||
4014 | |||||
4015 | return s->main_pid; | ||||
4016 | } | ||||
4017 | |||||
4018 | static int service_control_pid(Unit *u) { | ||||
4019 | Service *s = SERVICE(u); | ||||
4020 | |||||
4021 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 4021, __PRETTY_FUNCTION__ ); } while (0); | ||||
4022 | |||||
4023 | return s->control_pid; | ||||
4024 | } | ||||
4025 | |||||
4026 | static bool_Bool service_needs_console(Unit *u) { | ||||
4027 | Service *s = SERVICE(u); | ||||
4028 | |||||
4029 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/core/service.c", 4029, __PRETTY_FUNCTION__ ); } while (0); | ||||
4030 | |||||
4031 | /* We provide our own implementation of this here, instead of relying of the generic implementation | ||||
4032 | * unit_needs_console() provides, since we want to return false if we are in SERVICE_EXITED state. */ | ||||
4033 | |||||
4034 | if (!exec_context_may_touch_console(&s->exec_context)) | ||||
4035 | return false0; | ||||
4036 | |||||
4037 | return IN_SET(s->state,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
4038 | SERVICE_CONDITION,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
4039 | SERVICE_START_PRE,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
4040 | SERVICE_START,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
4041 | SERVICE_START_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
4042 | SERVICE_RUNNING,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
4043 | SERVICE_RELOAD,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
4044 | SERVICE_STOP,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
4045 | SERVICE_STOP_SIGABRT,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
4046 | SERVICE_STOP_SIGTERM,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
4047 | SERVICE_STOP_SIGKILL,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
4048 | SERVICE_STOP_POST,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
4049 | SERVICE_FINAL_SIGTERM,({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }) | ||||
4050 | SERVICE_FINAL_SIGKILL)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START , SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_STOP , SERVICE_STOP_SIGABRT, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL , SERVICE_STOP_POST, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL })/sizeof(int)]; switch(s->state) { case SERVICE_CONDITION : case SERVICE_START_PRE: case SERVICE_START: case SERVICE_START_POST : case SERVICE_RUNNING: case SERVICE_RELOAD: case SERVICE_STOP : case SERVICE_STOP_SIGABRT: case SERVICE_STOP_SIGTERM: case SERVICE_STOP_SIGKILL : case SERVICE_STOP_POST: case SERVICE_FINAL_SIGTERM: case SERVICE_FINAL_SIGKILL : _found = 1; break; default: break; } _found; }); | ||||
4051 | } | ||||
4052 | |||||
4053 | static const char* const service_restart_table[_SERVICE_RESTART_MAX] = { | ||||
4054 | [SERVICE_RESTART_NO] = "no", | ||||
4055 | [SERVICE_RESTART_ON_SUCCESS] = "on-success", | ||||
4056 | [SERVICE_RESTART_ON_FAILURE] = "on-failure", | ||||
4057 | [SERVICE_RESTART_ON_ABNORMAL] = "on-abnormal", | ||||
4058 | [SERVICE_RESTART_ON_WATCHDOG] = "on-watchdog", | ||||
4059 | [SERVICE_RESTART_ON_ABORT] = "on-abort", | ||||
4060 | [SERVICE_RESTART_ALWAYS] = "always", | ||||
4061 | }; | ||||
4062 | |||||
4063 | DEFINE_STRING_TABLE_LOOKUP(service_restart, ServiceRestart)const char *service_restart_to_string(ServiceRestart i) { if ( i < 0 || i >= (ServiceRestart) __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(service_restart_table) , typeof(&*(service_restart_table))), sizeof(service_restart_table )/sizeof((service_restart_table)[0]), ((void)0)))) return ((void *)0); return service_restart_table[i]; } ServiceRestart service_restart_from_string (const char *s) { return (ServiceRestart) string_table_lookup (service_restart_table, __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof(service_restart_table), typeof(&*(service_restart_table))), sizeof(service_restart_table )/sizeof((service_restart_table)[0]), ((void)0))), s); }; | ||||
4064 | |||||
4065 | static const char* const service_type_table[_SERVICE_TYPE_MAX] = { | ||||
4066 | [SERVICE_SIMPLE] = "simple", | ||||
4067 | [SERVICE_FORKING] = "forking", | ||||
4068 | [SERVICE_ONESHOT] = "oneshot", | ||||
4069 | [SERVICE_DBUS] = "dbus", | ||||
4070 | [SERVICE_NOTIFY] = "notify", | ||||
4071 | [SERVICE_IDLE] = "idle", | ||||
4072 | [SERVICE_EXEC] = "exec", | ||||
4073 | }; | ||||
4074 | |||||
4075 | DEFINE_STRING_TABLE_LOOKUP(service_type, ServiceType)const char *service_type_to_string(ServiceType i) { if (i < 0 || i >= (ServiceType) __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(service_type_table), typeof (&*(service_type_table))), sizeof(service_type_table)/sizeof ((service_type_table)[0]), ((void)0)))) return ((void*)0); return service_type_table[i]; } ServiceType service_type_from_string (const char *s) { return (ServiceType) string_table_lookup(service_type_table , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(service_type_table), typeof(&*(service_type_table ))), sizeof(service_type_table)/sizeof((service_type_table)[0 ]), ((void)0))), s); }; | ||||
4076 | |||||
4077 | static const char* const service_exec_command_table[_SERVICE_EXEC_COMMAND_MAX] = { | ||||
4078 | [SERVICE_EXEC_CONDITION] = "ExecCondition", | ||||
4079 | [SERVICE_EXEC_START_PRE] = "ExecStartPre", | ||||
4080 | [SERVICE_EXEC_START] = "ExecStart", | ||||
4081 | [SERVICE_EXEC_START_POST] = "ExecStartPost", | ||||
4082 | [SERVICE_EXEC_RELOAD] = "ExecReload", | ||||
4083 | [SERVICE_EXEC_STOP] = "ExecStop", | ||||
4084 | [SERVICE_EXEC_STOP_POST] = "ExecStopPost", | ||||
4085 | }; | ||||
4086 | |||||
4087 | DEFINE_STRING_TABLE_LOOKUP(service_exec_command, ServiceExecCommand)const char *service_exec_command_to_string(ServiceExecCommand i) { if (i < 0 || i >= (ServiceExecCommand) __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (service_exec_command_table), typeof(&*(service_exec_command_table ))), sizeof(service_exec_command_table)/sizeof((service_exec_command_table )[0]), ((void)0)))) return ((void*)0); return service_exec_command_table [i]; } ServiceExecCommand service_exec_command_from_string(const char *s) { return (ServiceExecCommand) string_table_lookup(service_exec_command_table , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(service_exec_command_table), typeof(&*(service_exec_command_table ))), sizeof(service_exec_command_table)/sizeof((service_exec_command_table )[0]), ((void)0))), s); }; | ||||
4088 | |||||
4089 | static const char* const notify_state_table[_NOTIFY_STATE_MAX] = { | ||||
4090 | [NOTIFY_UNKNOWN] = "unknown", | ||||
4091 | [NOTIFY_READY] = "ready", | ||||
4092 | [NOTIFY_RELOADING] = "reloading", | ||||
4093 | [NOTIFY_STOPPING] = "stopping", | ||||
4094 | }; | ||||
4095 | |||||
4096 | DEFINE_STRING_TABLE_LOOKUP(notify_state, NotifyState)const char *notify_state_to_string(NotifyState i) { if (i < 0 || i >= (NotifyState) __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(notify_state_table), typeof (&*(notify_state_table))), sizeof(notify_state_table)/sizeof ((notify_state_table)[0]), ((void)0)))) return ((void*)0); return notify_state_table[i]; } NotifyState notify_state_from_string (const char *s) { return (NotifyState) string_table_lookup(notify_state_table , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(notify_state_table), typeof(&*(notify_state_table ))), sizeof(notify_state_table)/sizeof((notify_state_table)[0 ]), ((void)0))), s); }; | ||||
4097 | |||||
4098 | static const char* const service_result_table[_SERVICE_RESULT_MAX] = { | ||||
4099 | [SERVICE_SUCCESS] = "success", | ||||
4100 | [SERVICE_FAILURE_RESOURCES] = "resources", | ||||
4101 | [SERVICE_FAILURE_PROTOCOL] = "protocol", | ||||
4102 | [SERVICE_FAILURE_TIMEOUT] = "timeout", | ||||
4103 | [SERVICE_FAILURE_EXIT_CODE] = "exit-code", | ||||
4104 | [SERVICE_FAILURE_SIGNAL] = "signal", | ||||
4105 | [SERVICE_FAILURE_CORE_DUMP] = "core-dump", | ||||
4106 | [SERVICE_FAILURE_WATCHDOG] = "watchdog", | ||||
4107 | [SERVICE_FAILURE_START_LIMIT_HIT] = "start-limit-hit", | ||||
4108 | [SERVICE_SKIP_CONDITION] = "exec-condition", | ||||
4109 | }; | ||||
4110 | |||||
4111 | DEFINE_STRING_TABLE_LOOKUP(service_result, ServiceResult)const char *service_result_to_string(ServiceResult i) { if (i < 0 || i >= (ServiceResult) __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(service_result_table), typeof(&*(service_result_table))), sizeof(service_result_table )/sizeof((service_result_table)[0]), ((void)0)))) return ((void *)0); return service_result_table[i]; } ServiceResult service_result_from_string (const char *s) { return (ServiceResult) string_table_lookup( service_result_table, __extension__ (__builtin_choose_expr( ! __builtin_types_compatible_p(typeof(service_result_table), typeof (&*(service_result_table))), sizeof(service_result_table) /sizeof((service_result_table)[0]), ((void)0))), s); }; | ||||
4112 | |||||
4113 | const UnitVTable service_vtable = { | ||||
4114 | .object_size = sizeof(Service), | ||||
4115 | .exec_context_offset = offsetof(Service, exec_context)__builtin_offsetof(Service, exec_context), | ||||
4116 | .cgroup_context_offset = offsetof(Service, cgroup_context)__builtin_offsetof(Service, cgroup_context), | ||||
4117 | .kill_context_offset = offsetof(Service, kill_context)__builtin_offsetof(Service, kill_context), | ||||
4118 | .exec_runtime_offset = offsetof(Service, exec_runtime)__builtin_offsetof(Service, exec_runtime), | ||||
4119 | .dynamic_creds_offset = offsetof(Service, dynamic_creds)__builtin_offsetof(Service, dynamic_creds), | ||||
4120 | |||||
4121 | .sections = | ||||
4122 | "Unit\0" | ||||
4123 | "Service\0" | ||||
4124 | "Install\0", | ||||
4125 | .private_section = "Service", | ||||
4126 | |||||
4127 | .can_transient = true1, | ||||
4128 | .can_delegate = true1, | ||||
4129 | |||||
4130 | .init = service_init, | ||||
4131 | .done = service_done, | ||||
4132 | .load = service_load, | ||||
4133 | .release_resources = service_release_resources, | ||||
4134 | |||||
4135 | .coldplug = service_coldplug, | ||||
4136 | |||||
4137 | .dump = service_dump, | ||||
4138 | |||||
4139 | .start = service_start, | ||||
4140 | .stop = service_stop, | ||||
4141 | .reload = service_reload, | ||||
4142 | |||||
4143 | .can_reload = service_can_reload, | ||||
4144 | |||||
4145 | .kill = service_kill, | ||||
4146 | |||||
4147 | .freeze = unit_freeze_vtable_common, | ||||
4148 | .thaw = unit_thaw_vtable_common, | ||||
4149 | |||||
4150 | .serialize = service_serialize, | ||||
4151 | .deserialize_item = service_deserialize_item, | ||||
4152 | |||||
4153 | .active_state = service_active_state, | ||||
4154 | .sub_state_to_string = service_sub_state_to_string, | ||||
4155 | |||||
4156 | .will_restart = service_will_restart, | ||||
4157 | |||||
4158 | .may_gc = service_may_gc, | ||||
4159 | |||||
4160 | .sigchld_event = service_sigchld_event, | ||||
4161 | |||||
4162 | .reset_failed = service_reset_failed, | ||||
4163 | |||||
4164 | .notify_cgroup_empty = service_notify_cgroup_empty_event, | ||||
4165 | .notify_message = service_notify_message, | ||||
4166 | |||||
4167 | .main_pid = service_main_pid, | ||||
4168 | .control_pid = service_control_pid, | ||||
4169 | |||||
4170 | .bus_name_owner_change = service_bus_name_owner_change, | ||||
4171 | |||||
4172 | .bus_vtable = bus_service_vtable, | ||||
4173 | .bus_set_property = bus_service_set_property, | ||||
4174 | .bus_commit_properties = bus_service_commit_properties, | ||||
4175 | |||||
4176 | .get_timeout = service_get_timeout, | ||||
4177 | .needs_console = service_needs_console, | ||||
4178 | |||||
4179 | .status_message_formats = { | ||||
4180 | .starting_stopping = { | ||||
4181 | [0] = "Starting %s...", | ||||
4182 | [1] = "Stopping %s...", | ||||
4183 | }, | ||||
4184 | .finished_start_job = { | ||||
4185 | [JOB_DONE] = "Started %s.", | ||||
4186 | [JOB_FAILED] = "Failed to start %s.", | ||||
4187 | [JOB_SKIPPED] = "Skipped %s.", | ||||
4188 | }, | ||||
4189 | .finished_stop_job = { | ||||
4190 | [JOB_DONE] = "Stopped %s.", | ||||
4191 | [JOB_FAILED] = "Stopped (with error) %s.", | ||||
4192 | }, | ||||
4193 | }, | ||||
4194 | }; |
1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2 | #pragma once |
3 | |
4 | #include <alloca.h> |
5 | #include <stddef.h> |
6 | #include <stdlib.h> |
7 | #include <string.h> |
8 | |
9 | #include "macro.h" |
10 | |
11 | #define new(t, n)((t*) malloc_multiply(sizeof(t), (n))) ((t*) malloc_multiply(sizeof(t), (n))) |
12 | |
13 | #define new0(t, n)((t*) calloc((n), sizeof(t))) ((t*) calloc((n), sizeof(t))) |
14 | |
15 | #define newa(t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 15, __PRETTY_FUNCTION__); } while (0); (t*) __builtin_alloca (sizeof(t)*(n)); }) \ |
16 | ({ \ |
17 | assert(!size_multiply_overflow(sizeof(t), n))do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 17, __PRETTY_FUNCTION__); } while (0); \ |
18 | (t*) alloca(sizeof(t)*(n))__builtin_alloca (sizeof(t)*(n)); \ |
19 | }) |
20 | |
21 | #define newa0(t, n)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 21, __PRETTY_FUNCTION__); } while (0); (t*) ({ char *_new_; size_t _len_ = sizeof(t)*(n); _new_ = __builtin_alloca (_len_); (void *) memset(_new_, 0, _len_) ; }); }) \ |
22 | ({ \ |
23 | assert(!size_multiply_overflow(sizeof(t), n))do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (t), n))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("!size_multiply_overflow(sizeof(t), n)" ), "../src/basic/alloc-util.h", 23, __PRETTY_FUNCTION__); } while (0); \ |
24 | (t*) alloca0(sizeof(t)*(n))({ char *_new_; size_t _len_ = sizeof(t)*(n); _new_ = __builtin_alloca (_len_); (void *) memset(_new_, 0, _len_); }); \ |
25 | }) |
26 | |
27 | #define newdup(t, p, n)((t*) memdup_multiply(p, sizeof(t), (n))) ((t*) memdup_multiply(p, sizeof(t), (n))) |
28 | |
29 | #define newdup_suffix0(t, p, n)((t*) memdup_suffix0_multiply(p, sizeof(t), (n))) ((t*) memdup_suffix0_multiply(p, sizeof(t), (n))) |
30 | |
31 | #define malloc0(n)(calloc(1, (n))) (calloc(1, (n))) |
32 | |
33 | static inline void *mfree(void *memory) { |
34 | free(memory); |
35 | return NULL((void*)0); |
36 | } |
37 | |
38 | #define free_and_replace(a, b)({ free(a); (a) = (b); (b) = ((void*)0); 0; }) \ |
39 | ({ \ |
40 | free(a); \ |
41 | (a) = (b); \ |
42 | (b) = NULL((void*)0); \ |
43 | 0; \ |
44 | }) |
45 | |
46 | void* memdup(const void *p, size_t l) _alloc_(2); |
47 | void* memdup_suffix0(const void *p, size_t l) _alloc_(2); |
48 | |
49 | static inline void freep(void *p) { |
50 | free(*(void**) p); |
51 | } |
52 | |
53 | #define _cleanup_free___attribute__((cleanup(freep))) _cleanup_(freep)__attribute__((cleanup(freep))) |
54 | |
55 | static inline bool_Bool size_multiply_overflow(size_t size, size_t need) { |
56 | return _unlikely_(need != 0 && size > (SIZE_MAX / need))(__builtin_expect(!!(need != 0 && size > ((18446744073709551615UL ) / need)),0)); |
57 | } |
58 | |
59 | _malloc___attribute__ ((malloc)) _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t need) { |
60 | if (size_multiply_overflow(size, need)) |
61 | return NULL((void*)0); |
62 | |
63 | return malloc(size * need); |
64 | } |
65 | |
66 | #if !HAVE_REALLOCARRAY1 |
67 | _alloc_(2, 3) static inline void *reallocarray(void *p, size_t need, size_t size) { |
68 | if (size_multiply_overflow(size, need)) |
69 | return NULL((void*)0); |
70 | |
71 | return realloc(p, size * need); |
72 | } |
73 | #endif |
74 | |
75 | _alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) { |
76 | if (size_multiply_overflow(size, need)) |
77 | return NULL((void*)0); |
78 | |
79 | return memdup(p, size * need); |
80 | } |
81 | |
82 | _alloc_(2, 3) static inline void *memdup_suffix0_multiply(const void *p, size_t size, size_t need) { |
83 | if (size_multiply_overflow(size, need)) |
84 | return NULL((void*)0); |
85 | |
86 | return memdup_suffix0(p, size * need); |
87 | } |
88 | |
89 | void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size); |
90 | void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size); |
91 | |
92 | #define GREEDY_REALLOC(array, allocated, need)greedy_realloc((void**) &(array), &(allocated), (need ), sizeof((array)[0])) \ |
93 | greedy_realloc((void**) &(array), &(allocated), (need), sizeof((array)[0])) |
94 | |
95 | #define GREEDY_REALLOC0(array, allocated, need)greedy_realloc0((void**) &(array), &(allocated), (need ), sizeof((array)[0])) \ |
96 | greedy_realloc0((void**) &(array), &(allocated), (need), sizeof((array)[0])) |
97 | |
98 | #define alloca0(n)({ char *_new_; size_t _len_ = n; _new_ = __builtin_alloca (_len_ ); (void *) memset(_new_, 0, _len_); }) \ |
99 | ({ \ |
100 | char *_new_; \ |
101 | size_t _len_ = n; \ |
102 | _new_ = alloca(_len_)__builtin_alloca (_len_); \ |
103 | (void *) memset(_new_, 0, _len_); \ |
104 | }) |
105 | |
106 | /* It's not clear what alignment glibc/gcc alloca() guarantee, hence provide a guaranteed safe version */ |
107 | #define alloca_align(size, align)({ void *_ptr_; size_t _mask_ = (align) - 1; _ptr_ = __builtin_alloca ((size) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); }) \ |
108 | ({ \ |
109 | void *_ptr_; \ |
110 | size_t _mask_ = (align) - 1; \ |
111 | _ptr_ = alloca((size) + _mask_)__builtin_alloca ((size) + _mask_); \ |
112 | (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); \ |
113 | }) |
114 | |
115 | #define alloca0_align(size, align)({ void *_new_; size_t _size_ = (size); _new_ = ({ void *_ptr_ ; size_t _mask_ = ((align)) - 1; _ptr_ = __builtin_alloca ((_size_ ) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_ ); }); (void*)memset(_new_, 0, _size_); }) \ |
116 | ({ \ |
117 | void *_new_; \ |
118 | size_t _size_ = (size); \ |
119 | _new_ = alloca_align(_size_, (align))({ void *_ptr_; size_t _mask_ = ((align)) - 1; _ptr_ = __builtin_alloca ((_size_) + _mask_); (void*)(((uintptr_t)_ptr_ + _mask_) & ~_mask_); }); \ |
120 | (void*)memset(_new_, 0, _size_); \ |
121 | }) |
122 | |
123 | /* Takes inspiration from Rusts's Option::take() method: reads and returns a pointer, but at the same time resets it to |
124 | * NULL. See: https://doc.rust-lang.org/std/option/enum.Option.html#method.take */ |
125 | #define TAKE_PTR(ptr)({ typeof(ptr) _ptr_ = (ptr); (ptr) = ((void*)0); _ptr_; }) \ |
126 | ({ \ |
127 | typeof(ptr) _ptr_ = (ptr); \ |
128 | (ptr) = NULL((void*)0); \ |
129 | _ptr_; \ |
130 | }) |