]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/core/service.c
Merge pull request #12753 from jrouleau/fix/hibernate-resume-timeout
[thirdparty/systemd.git] / src / core / service.c
index 0efd86188822b5b5bbfcc4de1d083a28b55c7bf2..4b50d8d02975f45e80a61befd621db6732cf762c 100644 (file)
@@ -320,10 +320,7 @@ static void service_fd_store_unlink(ServiceFDStore *fs) {
                 fs->service->n_fd_store--;
         }
 
-        if (fs->event_source) {
-                sd_event_source_set_enabled(fs->event_source, SD_EVENT_OFF);
-                sd_event_source_unref(fs->event_source);
-        }
+        sd_event_source_disable_unref(fs->event_source);
 
         free(fs->fdname);
         safe_close(fs->fd);
@@ -606,7 +603,7 @@ static int service_verify(Service *s) {
                 log_unit_warning(UNIT(s), "Service has USBFunctionStrings= setting, but no USBFunctionDescriptors=. Ignoring.");
 
         if (s->runtime_max_usec != USEC_INFINITY && s->type == SERVICE_ONESHOT)
-                log_unit_warning(UNIT(s), "MaxRuntimeSec= has no effect in combination with Type=oneshot. Ignoring.");
+                log_unit_warning(UNIT(s), "RuntimeMaxSec= has no effect in combination with Type=oneshot. Ignoring.");
 
         return 0;
 }
@@ -737,7 +734,7 @@ static int service_add_extras(Service *s) {
 
         /* If no OOM policy was explicitly set, then default to the configure default OOM policy. Except when
          * delegation is on, in that case it we assume the payload knows better what to do and can process
-         * things in a more focussed way. */
+         * things in a more focused way. */
         if (s->oom_policy < 0)
                 s->oom_policy = s->cgroup_context.delegate ? OOM_CONTINUE : UNIT(s)->manager->default_oom_policy;
 
@@ -861,16 +858,19 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
         fprintf(f,
                 "%sRestartSec: %s\n"
                 "%sTimeoutStartSec: %s\n"
-                "%sTimeoutStopSec: %s\n"
-                "%sTimeoutAbortSec: %s\n"
-                "%sRuntimeMaxSec: %s\n"
-                "%sWatchdogSec: %s\n",
+                "%sTimeoutStopSec: %s\n",
                 prefix, format_timespan(buf_restart, sizeof(buf_restart), s->restart_usec, USEC_PER_SEC),
                 prefix, format_timespan(buf_start, sizeof(buf_start), s->timeout_start_usec, USEC_PER_SEC),
-                prefix, format_timespan(buf_stop, sizeof(buf_stop), s->timeout_stop_usec, USEC_PER_SEC),
-                prefix, s->timeout_abort_set
-                                ? format_timespan(buf_abort, sizeof(buf_abort), s->timeout_abort_usec, USEC_PER_SEC)
-                                : "",
+                prefix, format_timespan(buf_stop, sizeof(buf_stop), s->timeout_stop_usec, USEC_PER_SEC));
+
+        if (s->timeout_abort_set)
+                fprintf(f,
+                        "%sTimeoutAbortSec: %s\n",
+                        prefix, format_timespan(buf_abort, sizeof(buf_abort), s->timeout_abort_usec, USEC_PER_SEC));
+
+        fprintf(f,
+                "%sRuntimeMaxSec: %s\n"
+                "%sWatchdogSec: %s\n",
                 prefix, format_timespan(buf_runtime, sizeof(buf_runtime), s->runtime_max_usec, USEC_PER_SEC),
                 prefix, format_timespan(buf_watchdog, sizeof(buf_watchdog), s->watchdog_usec, USEC_PER_SEC));
 
@@ -1749,7 +1749,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
                  * user can still introspect the counter. Do so on the next start. */
                 s->flush_n_restarts = true;
 
-        /* The new state is in effect, let's decrease the fd store ref counter again. Let's also readd us to the GC
+        /* The new state is in effect, let's decrease the fd store ref counter again. Let's also re-add us to the GC
          * queue, so that the fd store is possibly gc'ed again */
         s->n_keep_fd_store--;
         unit_add_to_gc_queue(UNIT(s));
@@ -2047,9 +2047,10 @@ static int service_adverse_to_leftover_processes(Service *s) {
          * aren't as rigoriously written to protect aganst against multiple use. */
         if (unit_warn_leftover_processes(UNIT(s)) &&
             IN_SET(s->kill_context.kill_mode, KILL_MIXED, KILL_CONTROL_GROUP) &&
-            !s->kill_context.send_sigkill) {
-               return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(EBUSY), "Will not start SendSIGKILL=no service of type KillMode=control-group or mixed while processes exist");
-        }
+            !s->kill_context.send_sigkill)
+               return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(EBUSY),
+                                           "Will not start SendSIGKILL=no service of type KillMode=control-group or mixed while processes exist");
+
         return 0;
 }
 
@@ -2092,7 +2093,7 @@ static void service_enter_start(Service *s) {
 
                 /* We force a fake state transition here. Otherwise, the unit would go directly from
                  * SERVICE_DEAD to SERVICE_DEAD without SERVICE_ACTIVATING or SERVICE_ACTIVE
-                 * inbetween. This way we can later trigger actions that depend on the state
+                 * in between. This way we can later trigger actions that depend on the state
                  * transition, including SuccessAction=. */
                 service_set_state(s, SERVICE_START);
 
@@ -3739,6 +3740,16 @@ static bool service_notify_message_authorized(Service *s, pid_t pid, char **tags
         return true;
 }
 
+static void service_force_watchdog(Service *s) {
+        if (!UNIT(s)->manager->service_watchdogs)
+                return;
+
+        log_unit_error(UNIT(s), "Watchdog request (last status: %s)!",
+                       s->status_text ? s->status_text : "<unset>");
+
+        service_enter_signal(s, SERVICE_STOP_WATCHDOG, SERVICE_FAILURE_WATCHDOG);
+}
+
 static void service_notify_message(
                 Unit *u,
                 const struct ucred *ucred,
@@ -3775,7 +3786,7 @@ static void service_notify_message(
 
                         r = service_is_suitable_main_pid(s, new_main_pid, LOG_WARNING);
                         if (r == 0) {
-                                /* The new main PID is a bit suspicous, which is OK if the sender is privileged. */
+                                /* The new main PID is a bit suspicious, which is OK if the sender is privileged. */
 
                                 if (ucred->uid == 0) {
                                         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);
@@ -3885,8 +3896,15 @@ static void service_notify_message(
         }
 
         /* Interpret WATCHDOG= */
-        if (strv_find(tags, "WATCHDOG=1"))
-                service_reset_watchdog(s);
+        e = strv_find_startswith(tags, "WATCHDOG=");
+        if (e) {
+                if (streq(e, "1"))
+                        service_reset_watchdog(s);
+                else if (streq(e, "trigger"))
+                        service_force_watchdog(s);
+                else
+                        log_unit_warning(u, "Passed WATCHDOG= field is invalid, ignoring.");
+        }
 
         e = strv_find_startswith(tags, "WATCHDOG_USEC=");
         if (e) {
@@ -4170,6 +4188,14 @@ static const char* const service_exec_command_table[_SERVICE_EXEC_COMMAND_MAX] =
 
 DEFINE_STRING_TABLE_LOOKUP(service_exec_command, ServiceExecCommand);
 
+static const char* const service_exec_ex_command_table[_SERVICE_EXEC_COMMAND_MAX] = {
+        [SERVICE_EXEC_START_PRE] = "ExecStartPreEx",
+        [SERVICE_EXEC_START] = "ExecStartEx",
+        [SERVICE_EXEC_START_POST] = "ExecStartPostEx",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(service_exec_ex_command, ServiceExecCommand);
+
 static const char* const notify_state_table[_NOTIFY_STATE_MAX] = {
         [NOTIFY_UNKNOWN] = "unknown",
         [NOTIFY_READY] = "ready",