Introduce ExitType
This commit is contained in:
committed by
Zbigniew Jędrzejewski-Szmek
parent
82a335db83
commit
cb0e818f7c
@@ -27,6 +27,7 @@
|
||||
#include "unit.h"
|
||||
|
||||
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_notify_access, notify_access, NotifyAccess);
|
||||
@@ -192,6 +193,7 @@ int bus_service_method_mount_image(sd_bus_message *message, void *userdata, sd_b
|
||||
const sd_bus_vtable bus_service_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
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("PIDFile", "s", NULL, offsetof(Service, pid_file), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@@ -377,6 +379,7 @@ static int bus_set_transient_std_fd(
|
||||
}
|
||||
static BUS_DEFINE_SET_TRANSIENT_PARSE(notify_access, NotifyAccess, notify_access_from_string);
|
||||
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(oom_policy, OOMPolicy, oom_policy_from_string);
|
||||
static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name, sd_bus_service_name_is_valid);
|
||||
@@ -414,6 +417,9 @@ static int bus_service_set_transient_property(
|
||||
if (streq(name, "Type"))
|
||||
return bus_set_transient_service_type(u, name, &s->type, message, flags, error);
|
||||
|
||||
if (streq(name, "ExitType"))
|
||||
return bus_set_transient_service_exit_type(u, name, &s->exit_type, message, flags, error);
|
||||
|
||||
if (streq(name, "OOMPolicy"))
|
||||
return bus_set_transient_oom_policy(u, name, &s->oom_policy, message, flags, error);
|
||||
|
||||
|
||||
@@ -359,6 +359,7 @@ Service.StartLimitAction, config_parse_emergency_action,
|
||||
Service.FailureAction, config_parse_emergency_action, 0, offsetof(Unit, failure_action)
|
||||
Service.RebootArgument, config_parse_unit_string_printf, 0, offsetof(Unit, reboot_arg)
|
||||
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.PermissionsStartOnly, config_parse_bool, 0, offsetof(Service, permissions_start_only)
|
||||
Service.RootDirectoryStartOnly, config_parse_bool, 0, offsetof(Service, root_directory_start_only)
|
||||
|
||||
@@ -130,6 +130,7 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_home, protect_home, ProtectHome, "
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_system, protect_system, ProtectSystem, "Failed to parse protect system value");
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_runtime_preserve_mode, exec_preserve_mode, ExecPreserveMode, "Failed to parse runtime directory preserve mode");
|
||||
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_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");
|
||||
@@ -5748,6 +5749,7 @@ void unit_dump_config_items(FILE *f) {
|
||||
{ config_parse_unit_deps, "UNIT [...]" },
|
||||
{ config_parse_exec, "PATH [ARGUMENT [...]]" },
|
||||
{ config_parse_service_type, "SERVICETYPE" },
|
||||
{ config_parse_service_exit_type, "SERVICEEXITTYPE" },
|
||||
{ config_parse_service_restart, "SERVICERESTART" },
|
||||
{ config_parse_service_timeout_failure_mode, "TIMEOUTMODE" },
|
||||
{ config_parse_kill_mode, "KILLMODE" },
|
||||
|
||||
@@ -32,6 +32,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout_abort);
|
||||
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_socket_bindtodevice);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_exec_output);
|
||||
|
||||
+29
-8
@@ -1621,18 +1621,25 @@ static int control_pid_good(Service *s) {
|
||||
return s->control_pid > 0;
|
||||
}
|
||||
|
||||
static int cgroup_good(Service *s) {
|
||||
int r;
|
||||
|
||||
static int cgroup_empty(Service *s) {
|
||||
assert(s);
|
||||
|
||||
/* Returns 0 if the cgroup is empty or doesn't exist, > 0 if it is exists and is populated, < 0 if we can't
|
||||
* figure it out */
|
||||
/* Returns 0 if there is no cgroup, > 0 if is empty or doesn't exist, < 0 if we can't figure it out */
|
||||
|
||||
if (!UNIT(s)->cgroup_path)
|
||||
return 0;
|
||||
|
||||
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path);
|
||||
return cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path);
|
||||
}
|
||||
|
||||
|
||||
static int cgroup_good(Service *s) {
|
||||
int r;
|
||||
|
||||
/* Returns 0 if the cgroup is empty or doesn't exist, > 0 if it is exists and is populated, < 0 if we can't
|
||||
* figure it out */
|
||||
|
||||
r = cgroup_empty(s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -3398,7 +3405,14 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
else
|
||||
assert_not_reached("Unknown code");
|
||||
|
||||
if (s->main_pid == pid) {
|
||||
/* Services with ExitType=cgroup ignore the main PID for purposes of exit status */
|
||||
if (s->exit_type == SERVICE_EXIT_CGROUP && s->main_pid == pid) {
|
||||
service_unwatch_main_pid(s);
|
||||
s->main_pid_known = false;
|
||||
}
|
||||
|
||||
if ((s->exit_type == SERVICE_EXIT_MAIN && s->main_pid == pid) ||
|
||||
(s->exit_type == SERVICE_EXIT_CGROUP && cgroup_empty(s) && !control_pid_good(s))) {
|
||||
/* Forking services may occasionally move to a new PID.
|
||||
* As long as they update the PID file before exiting the old
|
||||
* PID, they're fine. */
|
||||
@@ -3431,7 +3445,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
|
||||
unit_log_process_exit(
|
||||
u,
|
||||
"Main process",
|
||||
s->exit_type == SERVICE_EXIT_CGROUP ? "Last process" : "Main process",
|
||||
service_exec_command_to_string(SERVICE_EXEC_START),
|
||||
f == SERVICE_SUCCESS,
|
||||
code, status);
|
||||
@@ -4448,6 +4462,13 @@ static const char* const service_type_table[_SERVICE_TYPE_MAX] = {
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(service_type, ServiceType);
|
||||
|
||||
static const char* const service_exit_type_table[_SERVICE_EXIT_TYPE_MAX] = {
|
||||
[SERVICE_EXIT_MAIN] = "main",
|
||||
[SERVICE_EXIT_CGROUP] = "cgroup",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(service_exit_type, ServiceExitType);
|
||||
|
||||
static const char* const service_exec_command_table[_SERVICE_EXEC_COMMAND_MAX] = {
|
||||
[SERVICE_EXEC_CONDITION] = "ExecCondition",
|
||||
[SERVICE_EXEC_START_PRE] = "ExecStartPre",
|
||||
|
||||
@@ -35,6 +35,13 @@ typedef enum ServiceType {
|
||||
_SERVICE_TYPE_INVALID = -EINVAL,
|
||||
} ServiceType;
|
||||
|
||||
typedef enum ServiceExitType {
|
||||
SERVICE_EXIT_MAIN, /* we consider the main PID when deciding if the service exited */
|
||||
SERVICE_EXIT_CGROUP, /* we wait for the last process in the cgroup to exit */
|
||||
_SERVICE_EXIT_TYPE_MAX,
|
||||
_SERVICE_EXIT_TYPE_INVALID = -EINVAL,
|
||||
} ServiceExitType;
|
||||
|
||||
typedef enum ServiceExecCommand {
|
||||
SERVICE_EXEC_CONDITION,
|
||||
SERVICE_EXEC_START_PRE,
|
||||
@@ -97,6 +104,7 @@ struct Service {
|
||||
Unit meta;
|
||||
|
||||
ServiceType type;
|
||||
ServiceExitType exit_type;
|
||||
ServiceRestart restart;
|
||||
ExitStatusSet restart_prevent_status;
|
||||
ExitStatusSet restart_force_status;
|
||||
@@ -226,6 +234,9 @@ ServiceRestart service_restart_from_string(const char *s) _pure_;
|
||||
const char* service_type_to_string(ServiceType i) _const_;
|
||||
ServiceType service_type_from_string(const char *s) _pure_;
|
||||
|
||||
const char* service_exit_type_to_string(ServiceExitType i) _const_;
|
||||
ServiceExitType service_exit_type_from_string(const char *s) _pure_;
|
||||
|
||||
const char* service_exec_command_to_string(ServiceExecCommand i) _const_;
|
||||
ServiceExecCommand service_exec_command_from_string(const char *s) _pure_;
|
||||
|
||||
|
||||
@@ -1947,6 +1947,7 @@ static int bus_append_service_property(sd_bus_message *m, const char *field, con
|
||||
|
||||
if (STR_IN_SET(field, "PIDFile",
|
||||
"Type",
|
||||
"ExitType",
|
||||
"Restart",
|
||||
"BusName",
|
||||
"NotifyAccess",
|
||||
|
||||
@@ -599,6 +599,7 @@ int xdg_autostart_service_generate_unit(
|
||||
fprintf(f,
|
||||
"\n[Service]\n"
|
||||
"Type=exec\n"
|
||||
"ExitType=cgroup\n"
|
||||
"ExecStart=:%s\n"
|
||||
"Restart=no\n"
|
||||
"TimeoutSec=5s\n"
|
||||
|
||||
Reference in New Issue
Block a user