diff options
author | Richard Phibel <rphibel@googlemail.com> | 2023-07-06 14:33:52 +0200 |
---|---|---|
committer | Richard Phibel <rphibel@googlemail.com> | 2023-07-06 14:33:52 +0200 |
commit | e568fea9fcd2189d4366df254a8a4031dc433762 (patch) | |
tree | 19ca4fa497560b5516319dba14cef427cb841f8d /src | |
parent | treewide: fix "an" before consonant U sounds (diff) | |
download | systemd-e568fea9fcd2189d4366df254a8a4031dc433762.tar.xz systemd-e568fea9fcd2189d4366df254a8a4031dc433762.zip |
service: add new RestartMode option
When this option is set to direct, the service restarts without entering a failed
state. Dependent units are not notified of transitory failure.
This is useful for the following use case:
We have a target with Requires=my-service, After=my-service.
my-service.service is a oneshot service and has Restart=on-failure in
its definition.
my-service.service can get stuck for various reasons and time out, in
which case it is restarted. Currently, when it fails the first time, the
target fails, even though my-service is restarted.
The behavior we're looking for is that until my-service is not restarted
anymore, the target stays pending waiting for my-service.service to
start successfully or fail without being restarted anymore.
Diffstat (limited to 'src')
-rw-r--r-- | src/core/dbus-service.c | 6 | ||||
-rw-r--r-- | src/core/load-fragment-gperf.gperf.in | 1 | ||||
-rw-r--r-- | src/core/load-fragment.c | 2 | ||||
-rw-r--r-- | src/core/load-fragment.h | 1 | ||||
-rw-r--r-- | src/core/service.c | 10 | ||||
-rw-r--r-- | src/core/service.h | 11 | ||||
-rw-r--r-- | src/shared/bus-unit-util.c | 1 | ||||
-rw-r--r-- | src/test/test-tables.c | 1 |
8 files changed, 32 insertions, 1 deletions
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index ea82a665a6..6068c742ca 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -33,6 +33,7 @@ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exit_type, service_exit_type, ServiceExitType); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart_mode, service_restart_mode, ServiceRestartMode); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction); static BUS_DEFINE_PROPERTY_GET2(property_get_notify_access, "s", Service, service_get_notify_access, notify_access_to_string); static BUS_DEFINE_PROPERTY_GET(property_get_restart_usec_next, "t", Service, service_restart_usec_next); @@ -322,6 +323,7 @@ const sd_bus_vtable bus_service_vtable[] = { SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ExitType", "s", property_get_exit_type, offsetof(Service, exit_type), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RestartMode", "s", property_get_restart_mode, offsetof(Service, restart_mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), SD_BUS_VTABLE_PROPERTY_CONST), @@ -512,6 +514,7 @@ static BUS_DEFINE_SET_TRANSIENT_PARSE(notify_access, NotifyAccess, notify_access static BUS_DEFINE_SET_TRANSIENT_PARSE(service_type, ServiceType, service_type_from_string); static BUS_DEFINE_SET_TRANSIENT_PARSE(service_exit_type, ServiceExitType, service_exit_type_from_string); static BUS_DEFINE_SET_TRANSIENT_PARSE(service_restart, ServiceRestart, service_restart_from_string); +static BUS_DEFINE_SET_TRANSIENT_PARSE(service_restart_mode, ServiceRestartMode, service_restart_mode_from_string); static BUS_DEFINE_SET_TRANSIENT_PARSE(oom_policy, OOMPolicy, oom_policy_from_string); static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name, sd_bus_service_name_is_valid); static BUS_DEFINE_SET_TRANSIENT_PARSE(timeout_failure_mode, ServiceTimeoutFailureMode, service_timeout_failure_mode_from_string); @@ -660,6 +663,9 @@ static int bus_service_set_transient_property( if (streq(name, "Restart")) return bus_set_transient_service_restart(u, name, &s->restart, message, flags, error); + if (streq(name, "RestartMode")) + return bus_set_transient_service_restart_mode(u, name, &s->restart_mode, message, flags, error); + if (streq(name, "RestartPreventExitStatus")) return bus_set_transient_exit_status(u, name, &s->restart_prevent_status, message, flags, error); diff --git a/src/core/load-fragment-gperf.gperf.in b/src/core/load-fragment-gperf.gperf.in index 382b60ea90..b66adf2811 100644 --- a/src/core/load-fragment-gperf.gperf.in +++ b/src/core/load-fragment-gperf.gperf.in @@ -427,6 +427,7 @@ Service.RebootArgument, config_parse_unit_string_printf, Service.Type, config_parse_service_type, 0, offsetof(Service, type) Service.ExitType, config_parse_service_exit_type, 0, offsetof(Service, exit_type) Service.Restart, config_parse_service_restart, 0, offsetof(Service, restart) +Service.RestartMode, config_parse_service_restart_mode, 0, offsetof(Service, restart_mode) Service.PermissionsStartOnly, config_parse_bool, 0, offsetof(Service, permissions_start_only) Service.RootDirectoryStartOnly, config_parse_bool, 0, offsetof(Service, root_directory_start_only) Service.RemainAfterExit, config_parse_bool, 0, offsetof(Service, remain_after_exit) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index f0f60cf2ab..c69d47c228 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -142,6 +142,7 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_preserve_mode, exec_preserve_mode, Ex DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type"); DEFINE_CONFIG_PARSE_ENUM(config_parse_service_exit_type, service_exit_type, ServiceExitType, "Failed to parse service exit type"); DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier"); +DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart_mode, service_restart_mode, ServiceRestartMode, "Failed to parse service restart mode"); DEFINE_CONFIG_PARSE_ENUM(config_parse_service_timeout_failure_mode, service_timeout_failure_mode, ServiceTimeoutFailureMode, "Failed to parse timeout failure mode"); DEFINE_CONFIG_PARSE_ENUM(config_parse_socket_bind, socket_address_bind_ipv6_only_or_bool, SocketAddressBindIPv6Only, "Failed to parse bind IPv6 only value"); DEFINE_CONFIG_PARSE_ENUM(config_parse_oom_policy, oom_policy, OOMPolicy, "Failed to parse OOM policy"); @@ -6299,6 +6300,7 @@ void unit_dump_config_items(FILE *f) { { config_parse_service_type, "SERVICETYPE" }, { config_parse_service_exit_type, "SERVICEEXITTYPE" }, { config_parse_service_restart, "SERVICERESTART" }, + { config_parse_service_restart_mode, "SERVICERESTARTMODE" }, { config_parse_service_timeout_failure_mode, "TIMEOUTMODE" }, { config_parse_kill_mode, "KILLMODE" }, { config_parse_signal, "SIGNAL" }, diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index 3cfb50969a..39378b3a3c 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -41,6 +41,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout_failure_mode); CONFIG_PARSER_PROTOTYPE(config_parse_service_type); CONFIG_PARSER_PROTOTYPE(config_parse_service_exit_type); CONFIG_PARSER_PROTOTYPE(config_parse_service_restart); +CONFIG_PARSER_PROTOTYPE(config_parse_service_restart_mode); CONFIG_PARSER_PROTOTYPE(config_parse_socket_bindtodevice); CONFIG_PARSER_PROTOTYPE(config_parse_exec_output); CONFIG_PARSER_PROTOTYPE(config_parse_exec_input); diff --git a/src/core/service.c b/src/core/service.c index a90b4de536..c6178cf2cd 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -2011,7 +2011,8 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) * are only transitionary and followed by an automatic restart. We have fine-grained * low-level states for this though so that software can distinguish the permanent UNIT_INACTIVE * state from this transitionary UNIT_INACTIVE state by looking at the low-level states. */ - service_set_state(s, restart_state); + if (s->restart_mode != SERVICE_RESTART_MODE_DIRECT) + service_set_state(s, restart_state); r = service_arm_timer(s, /* relative= */ true, service_restart_usec_next(s)); if (r < 0) @@ -5009,6 +5010,13 @@ static const char* const service_restart_table[_SERVICE_RESTART_MAX] = { DEFINE_STRING_TABLE_LOOKUP(service_restart, ServiceRestart); +static const char* const service_restart_mode_table[_SERVICE_RESTART_MODE_MAX] = { + [SERVICE_RESTART_MODE_NORMAL] = "normal", + [SERVICE_RESTART_MODE_DIRECT] = "direct", +}; + +DEFINE_STRING_TABLE_LOOKUP(service_restart_mode, ServiceRestartMode); + static const char* const service_type_table[_SERVICE_TYPE_MAX] = { [SERVICE_SIMPLE] = "simple", [SERVICE_FORKING] = "forking", diff --git a/src/core/service.h b/src/core/service.h index 0e578c9280..3bf5fb1e14 100644 --- a/src/core/service.h +++ b/src/core/service.h @@ -91,6 +91,13 @@ typedef enum ServiceTimeoutFailureMode { _SERVICE_TIMEOUT_FAILURE_MODE_INVALID = -EINVAL, } ServiceTimeoutFailureMode; +typedef enum ServiceRestartMode { + SERVICE_RESTART_MODE_NORMAL, + SERVICE_RESTART_MODE_DIRECT, + _SERVICE_RESTART_MODE_MAX, + _SERVICE_RESTART_MODE_INVALID = -EINVAL, +} ServiceRestartMode; + struct ServiceFDStore { Service *service; @@ -108,6 +115,7 @@ struct Service { ServiceType type; ServiceExitType exit_type; ServiceRestart restart; + ServiceRestartMode restart_mode; ExitStatusSet restart_prevent_status; ExitStatusSet restart_force_status; ExitStatusSet success_status; @@ -249,6 +257,9 @@ usec_t service_restart_usec_next(Service *s); const char* service_restart_to_string(ServiceRestart i) _const_; ServiceRestart service_restart_from_string(const char *s) _pure_; +const char* service_restart_mode_to_string(ServiceRestartMode i) _const_; +ServiceRestartMode service_restart_mode_from_string(const char *s) _pure_; + const char* service_type_to_string(ServiceType i) _const_; ServiceType service_type_from_string(const char *s) _pure_; diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index cc287feb8e..494484f0bf 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -2206,6 +2206,7 @@ static int bus_append_service_property(sd_bus_message *m, const char *field, con "Type", "ExitType", "Restart", + "RestartMode", "BusName", "NotifyAccess", "USBFunctionDescriptors", diff --git a/src/test/test-tables.c b/src/test/test-tables.c index 6301dedb09..db41c69df5 100644 --- a/src/test/test-tables.c +++ b/src/test/test-tables.c @@ -95,6 +95,7 @@ int main(int argc, char **argv) { test_table(scope_state, SCOPE_STATE); test_table(service_exec_command, SERVICE_EXEC_COMMAND); test_table(service_restart, SERVICE_RESTART); + test_table(service_restart_mode, SERVICE_RESTART_MODE); test_table(service_result, SERVICE_RESULT); test_table(service_state, SERVICE_STATE); test_table(service_type, SERVICE_TYPE); |