File: | build-scan/../src/core/service.c |
Warning: | line 1215, column 33 Potential leak of memory pointed to by 'rfds' |
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 < 0) | |||
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 | }) |