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