diff --git a/man/systemd.service.xml b/man/systemd.service.xml index fe83581b6e..ada92369e1 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -893,14 +893,6 @@ effect. - - FailureAction= - Configure the action to take when the service enters a failed state. Takes the same values as - the unit setting StartLimitAction= and executes the same actions (see - systemd.unit5). Defaults to - . - - FileDescriptorStoreMax= Configure how many file descriptors may be stored in the service manager for the service using diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml index 6047524623..6e9cdaebcf 100644 --- a/man/systemd.unit.xml +++ b/man/systemd.unit.xml @@ -877,11 +877,19 @@ semantics. Defaults to . + + FailureAction= + Configure the action to take when the unit enters the failed state. Takes the same values as + the setting StartLimitAction= setting and executes the same actions (see + systemd.unit5). Defaults to + . + + RebootArgument= Configure the optional argument for the reboot2 system call if - StartLimitAction= or a service's FailureAction= is a reboot action. This + StartLimitAction= or FailureAction= is a reboot action. This works just like the optional argument to systemctl reboot command. diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index 6b83982cf8..7b6cb395d8 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -51,7 +51,6 @@ const sd_bus_vtable bus_service_vtable[] = { SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST), BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0), - SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Service, emergency_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), SD_BUS_VTABLE_PROPERTY_CONST), @@ -82,6 +81,7 @@ const sd_bus_vtable bus_service_vtable[] = { SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), + SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), SD_BUS_VTABLE_END }; diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c index 7e5c889830..5344183508 100644 --- a/src/core/dbus-unit.c +++ b/src/core/dbus-unit.c @@ -798,6 +798,7 @@ const sd_bus_vtable bus_unit_vtable[] = { SD_BUS_PROPERTY("StartLimitIntervalSec", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("InvocationID", "ay", bus_property_get_id128, offsetof(Unit, invocation_id), 0), SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), 0), diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 73b13977ed..5fc3371170 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -223,6 +223,7 @@ m4_dnl The following is a legacy alias name for compatibility Unit.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval) Unit.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst) Unit.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action) +Unit.FailureAction, config_parse_emergency_action, 0, offsetof(Unit, failure_action) Unit.RebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, reboot_arg) Unit.ConditionPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, conditions) Unit.ConditionPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, conditions) @@ -281,12 +282,12 @@ Service.TimeoutStartSec, config_parse_service_timeout, 0, Service.TimeoutStopSec, config_parse_service_timeout, 0, 0 Service.RuntimeMaxSec, config_parse_sec, 0, offsetof(Service, runtime_max_usec) Service.WatchdogSec, config_parse_sec, 0, offsetof(Service, watchdog_usec) -m4_dnl The following three only exist for compatibility, they moved into Unit, see above +m4_dnl The following five only exist for compatibility, they moved into Unit, see above Service.StartLimitInterval, config_parse_sec, 0, offsetof(Unit, start_limit.interval) Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Unit, start_limit.burst) Service.StartLimitAction, config_parse_emergency_action, 0, offsetof(Unit, start_limit_action) +Service.FailureAction, config_parse_emergency_action, 0, offsetof(Unit, failure_action) Service.RebootArgument, config_parse_unit_path_printf, 0, offsetof(Unit, reboot_arg) -Service.FailureAction, config_parse_emergency_action, 0, offsetof(Service, emergency_action) Service.Type, config_parse_service_type, 0, offsetof(Service, type) Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart) Service.PermissionsStartOnly, config_parse_bool, 0, offsetof(Service, permissions_start_only) diff --git a/src/core/service.c b/src/core/service.c index 445d1becc1..1dfde82816 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1532,9 +1532,6 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) service_set_state(s, s->result != SERVICE_SUCCESS ? SERVICE_FAILED : SERVICE_DEAD); - if (s->result != SERVICE_SUCCESS) - emergency_action(UNIT(s)->manager, s->emergency_action, UNIT(s)->reboot_arg, "service failed"); - if (allow_restart && service_shall_restart(s)) { r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->restart_usec)); diff --git a/src/core/service.h b/src/core/service.h index a529f48a63..a995c89605 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -174,8 +174,6 @@ struct Service { char *status_text; int status_errno; - EmergencyAction emergency_action; - UnitRef accept_socket; sd_event_source *timer_event_source; diff --git a/src/core/unit.c b/src/core/unit.c index d5e6b3891b..07656c117f 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2503,6 +2503,9 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su * units go directly from starting to inactive, * without ever entering started.) */ unit_check_binds_to(u); + + if (os != UNIT_FAILED && ns == UNIT_FAILED) + (void) emergency_action(u->manager, u->failure_action, u->reboot_arg, "unit failed"); } unit_add_to_dbus_queue(u); diff --git a/src/core/unit.h b/src/core/unit.h index 2b11a285d4..d3403cba20 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -248,6 +248,8 @@ struct Unit { /* Put a ratelimit on unit starting */ RateLimit start_limit; EmergencyAction start_limit_action; + + EmergencyAction failure_action; char *reboot_arg; /* Make sure we never enter endless loops with the check unneeded logic, or the BindsTo= logic */