core: generalize FailureAction= move it from service to unit

All kinds of units can fail, hence it makes sense to offer this as
generic concept for all unit types.
This commit is contained in:
Lennart Poettering 2017-11-16 15:02:56 +01:00
parent 9990ea0e59
commit 53c35a766f
9 changed files with 19 additions and 17 deletions

View File

@ -893,14 +893,6 @@
effect.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>FailureAction=</varname></term>
<listitem><para>Configure the action to take when the service enters a failed state. Takes the same values as
the unit setting <varname>StartLimitAction=</varname> and executes the same actions (see
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>). Defaults to
<option>none</option>. </para></listitem>
</varlistentry>
<varlistentry>
<term><varname>FileDescriptorStoreMax=</varname></term>
<listitem><para>Configure how many file descriptors may be stored in the service manager for the service using

View File

@ -877,11 +877,19 @@
semantics. Defaults to <option>none</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>FailureAction=</varname></term>
<listitem><para>Configure the action to take when the unit enters the failed state. Takes the same values as
the setting <varname>StartLimitAction=</varname> setting and executes the same actions (see
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>). Defaults to
<option>none</option>. </para></listitem>
</varlistentry>
<varlistentry>
<term><varname>RebootArgument=</varname></term>
<listitem><para>Configure the optional argument for the
<citerefentry><refentrytitle>reboot</refentrytitle><manvolnum>2</manvolnum></citerefentry> system call if
<varname>StartLimitAction=</varname> or a service's <varname>FailureAction=</varname> is a reboot action. This
<varname>StartLimitAction=</varname> or <varname>FailureAction=</varname> is a reboot action. This
works just like the optional argument to <command>systemctl reboot</command> command.</para></listitem>
</varlistentry>

View File

@ -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
};

View File

@ -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),

View File

@ -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)

View File

@ -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));

View File

@ -174,8 +174,6 @@ struct Service {
char *status_text;
int status_errno;
EmergencyAction emergency_action;
UnitRef accept_socket;
sd_event_source *timer_event_source;

View File

@ -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);

View File

@ -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 */