diff options
-rw-r--r-- | man/systemd.service.xml | 11 | ||||
-rw-r--r-- | src/core/dbus-service.c | 1 | ||||
-rw-r--r-- | src/core/load-fragment-gperf.gperf.m4 | 1 | ||||
-rw-r--r-- | src/core/service.c | 39 | ||||
-rw-r--r-- | src/core/service.h | 2 |
5 files changed, 40 insertions, 14 deletions
diff --git a/man/systemd.service.xml b/man/systemd.service.xml index a2a1b6b508..af32ccb878 100644 --- a/man/systemd.service.xml +++ b/man/systemd.service.xml @@ -1030,6 +1030,17 @@ ExecStart=/bin/echo $ONE $TWO ${TWO}</programlisting> command.</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 + <varname>StartLimitAction=</varname> + and executes the same actions. + Defaults to <option>none</option>. + </para></listitem> + </varlistentry> + </variablelist> <para>Check diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index 45bfecf80d..2f9c25a48a 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -51,6 +51,7 @@ const sd_bus_vtable bus_service_vtable[] = { SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Service, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StartLimitAction", "s", property_get_start_limit_action, offsetof(Service, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Service, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("FailureAction", "s", property_get_start_limit_action, offsetof(Service, failure_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), diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index cb98c830b3..da6df5ca3c 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -181,6 +181,7 @@ Service.StartLimitInterval, config_parse_sec, 0, Service.StartLimitBurst, config_parse_unsigned, 0, offsetof(Service, start_limit.burst) Service.StartLimitAction, config_parse_start_limit_action, 0, offsetof(Service, start_limit_action) Service.RebootArgument, config_parse_string, 0, offsetof(Service, reboot_arg) +Service.FailureAction, config_parse_start_limit_action, 0, offsetof(Service, failure_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 4ebce6aa95..593237a0ad 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1840,6 +1840,8 @@ static int cgroup_good(Service *s) { return !r; } +static int service_execute_action(Service *s, StartLimitAction action, const char *reason, bool log_action_none); + static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) { int r; assert(s); @@ -1849,6 +1851,9 @@ 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) + service_execute_action(s, s->failure_action, "failed", false); + if (allow_restart && !s->forbid_restart && (s->restart == SERVICE_RESTART_ALWAYS || @@ -2371,22 +2376,19 @@ fail: service_enter_stop(s, SERVICE_FAILURE_RESOURCES); } -static int service_start_limit_test(Service *s) { +static int service_execute_action(Service *s, StartLimitAction action, const char *reason, bool log_action_none) { assert(s); - if (ratelimit_test(&s->start_limit)) - return 0; - - if (s->start_limit_action == SERVICE_START_LIMIT_REBOOT || - s->start_limit_action == SERVICE_START_LIMIT_REBOOT_FORCE) + if (action == SERVICE_START_LIMIT_REBOOT || + action == SERVICE_START_LIMIT_REBOOT_FORCE) update_reboot_param_file(s->reboot_arg); - switch (s->start_limit_action) { + switch (action) { case SERVICE_START_LIMIT_NONE: - log_warning_unit(UNIT(s)->id, - "%s start request repeated too quickly, refusing to start.", - UNIT(s)->id); + if (log_action_none) + log_warning_unit(UNIT(s)->id, + "%s %s, refusing to start.", UNIT(s)->id, reason); break; case SERVICE_START_LIMIT_REBOOT: { @@ -2394,7 +2396,7 @@ static int service_start_limit_test(Service *s) { int r; log_warning_unit(UNIT(s)->id, - "%s start request repeated too quickly, rebooting.", UNIT(s)->id); + "%s %s, rebooting.", UNIT(s)->id, reason); r = manager_add_job_by_name(UNIT(s)->manager, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE, @@ -2408,13 +2410,13 @@ static int service_start_limit_test(Service *s) { case SERVICE_START_LIMIT_REBOOT_FORCE: log_warning_unit(UNIT(s)->id, - "%s start request repeated too quickly, forcibly rebooting.", UNIT(s)->id); + "%s %s, forcibly rebooting.", UNIT(s)->id, reason); UNIT(s)->manager->exit_code = MANAGER_REBOOT; break; case SERVICE_START_LIMIT_REBOOT_IMMEDIATE: log_warning_unit(UNIT(s)->id, - "%s start request repeated too quickly, rebooting immediately.", UNIT(s)->id); + "%s %s, rebooting immediately.", UNIT(s)->id, reason); sync(); if (s->reboot_arg) { log_info("Rebooting with argument '%s'.", s->reboot_arg); @@ -2428,13 +2430,22 @@ static int service_start_limit_test(Service *s) { default: log_error_unit(UNIT(s)->id, - "start limit action=%i", s->start_limit_action); + "start limit action=%i", action); assert_not_reached("Unknown StartLimitAction."); } return -ECANCELED; } +static int service_start_limit_test(Service *s) { + assert(s); + + if (ratelimit_test(&s->start_limit)) + return 0; + + return service_execute_action(s, s->start_limit_action, "start request repeated too quickly", true); +} + static int service_start(Unit *u) { Service *s = SERVICE(u); int r; diff --git a/src/core/service.h b/src/core/service.h index fd05e9be89..13b2b064c0 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -187,6 +187,8 @@ struct Service { char *status_text; + StartLimitAction failure_action; + RateLimit start_limit; StartLimitAction start_limit_action; char *reboot_arg; |