mirror of
https://github.com/systemd/systemd.git
synced 2024-11-06 08:26:52 +03:00
service: add StartLimitInterval/StartLimitBurst/StartLimitAction
This commit is contained in:
parent
54f5e17193
commit
4b9397474f
@ -46,6 +46,9 @@
|
||||
" <property name=\"WatchdogUSec\" type=\"t\" access=\"read\"/>\n" \
|
||||
" <property name=\"WatchdogTimestamp\" type=\"t\" access=\"read\"/>\n" \
|
||||
" <property name=\"WatchdogTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \
|
||||
" <property name=\"StartLimitInterval\" type=\"t\" access=\"read\"/>\n" \
|
||||
" <property name=\"StartLimitBurst\" type=\"u\" access=\"read\"/>\n" \
|
||||
" <property name=\"StartLimitAction\" type=\"s\" access=\"read\"/>\n" \
|
||||
BUS_EXEC_COMMAND_INTERFACE("ExecStartPre") \
|
||||
BUS_EXEC_COMMAND_INTERFACE("ExecStart") \
|
||||
BUS_EXEC_COMMAND_INTERFACE("ExecStartPost") \
|
||||
@ -101,6 +104,7 @@ static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_type, service_type, Se
|
||||
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_restart, service_restart, ServiceRestart);
|
||||
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_notify_access, notify_access, NotifyAccess);
|
||||
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_service_result, service_result, ServiceResult);
|
||||
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_start_limit_action, start_limit_action, StartLimitAction);
|
||||
|
||||
static const BusProperty bus_exec_main_status_properties[] = {
|
||||
{ "ExecMainStartTimestamp", bus_property_append_usec, "t", offsetof(ExecStatus, start_timestamp.realtime) },
|
||||
@ -123,6 +127,9 @@ static const BusProperty bus_service_properties[] = {
|
||||
{ "WatchdogUSec", bus_property_append_usec, "t", offsetof(Service, watchdog_usec) },
|
||||
{ "WatchdogTimestamp", bus_property_append_usec, "t", offsetof(Service, watchdog_timestamp.realtime) },
|
||||
{ "WatchdogTimestampMonotonic",bus_property_append_usec, "t", offsetof(Service, watchdog_timestamp.monotonic) },
|
||||
{ "StartLimitInterval", bus_property_append_usec, "t", offsetof(Service, start_limit.interval) },
|
||||
{ "StartLimitBurst", bus_property_append_uint32, "u", offsetof(Service, start_limit.burst) },
|
||||
{ "StartLimitAction", bus_service_append_start_limit_action,"s", offsetof(Service, start_limit_action) },
|
||||
BUS_EXEC_COMMAND_PROPERTY("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), true ),
|
||||
BUS_EXEC_COMMAND_PROPERTY("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), true ),
|
||||
BUS_EXEC_COMMAND_PROPERTY("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), true ),
|
||||
|
@ -136,6 +136,9 @@ Service.ExecStopPost, config_parse_exec, SERVICE_EXE
|
||||
Service.RestartSec, config_parse_usec, 0, offsetof(Service, restart_usec)
|
||||
Service.TimeoutSec, config_parse_usec, 0, offsetof(Service, timeout_usec)
|
||||
Service.WatchdogSec, config_parse_usec, 0, offsetof(Service, watchdog_usec)
|
||||
Service.StartLimitInterval, config_parse_usec, 0, offsetof(Service, start_limit.interval)
|
||||
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.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)
|
||||
|
@ -1648,6 +1648,7 @@ int config_parse_unit_condition_null(
|
||||
}
|
||||
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_start_limit_action, start_limit_action, StartLimitAction, "Failed to parse start limit action specifier");
|
||||
|
||||
int config_parse_unit_cgroup_attr(
|
||||
const char *filename,
|
||||
|
@ -76,6 +76,7 @@ int config_parse_unit_condition_string(const char *filename, unsigned line, cons
|
||||
int config_parse_unit_condition_null(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_kill_mode(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_notify_access(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_start_limit_action(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_unit_cgroup_attr(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_unit_cpu_shares(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_unit_memory_limit(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
@ -23,7 +23,9 @@
|
||||
#include <signal.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/reboot.h>
|
||||
|
||||
#include "manager.h"
|
||||
#include "unit.h"
|
||||
#include "service.h"
|
||||
#include "load-fragment.h"
|
||||
@ -125,7 +127,7 @@ static void service_init(Unit *u) {
|
||||
|
||||
exec_context_init(&s->exec_context);
|
||||
|
||||
RATELIMIT_INIT(s->ratelimit, 10*USEC_PER_SEC, 5);
|
||||
RATELIMIT_INIT(s->start_limit, 10*USEC_PER_SEC, 5);
|
||||
|
||||
s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
|
||||
}
|
||||
@ -2324,8 +2326,56 @@ fail:
|
||||
service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
|
||||
}
|
||||
|
||||
static int service_start_limit_test(Service *s) {
|
||||
assert(s);
|
||||
|
||||
if (ratelimit_test(&s->start_limit))
|
||||
return 0;
|
||||
|
||||
switch (s->start_limit_action) {
|
||||
|
||||
case SERVICE_START_LIMIT_NONE:
|
||||
log_warning("%s start request repeated too quickly, refusing to start.", UNIT(s)->id);
|
||||
break;
|
||||
|
||||
case SERVICE_START_LIMIT_REBOOT: {
|
||||
DBusError error;
|
||||
int r;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
log_warning("%s start request repeated too quickly, rebooting.", UNIT(s)->id);
|
||||
|
||||
r = manager_add_job_by_name(UNIT(s)->manager, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE, true, &error, NULL);
|
||||
if (r < 0) {
|
||||
log_error("Failed to reboot: %s.", bus_error(&error, r));
|
||||
dbus_error_free(&error);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SERVICE_START_LIMIT_REBOOT_FORCE:
|
||||
log_warning("%s start request repeated too quickly, force rebooting.", UNIT(s)->id);
|
||||
UNIT(s)->manager->exit_code = MANAGER_REBOOT;
|
||||
break;
|
||||
|
||||
case SERVICE_START_LIMIT_REBOOT_IMMEDIATE:
|
||||
log_warning("%s start request repeated too quickly, rebooting immediately.", UNIT(s)->id);
|
||||
reboot(RB_AUTOBOOT);
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("start limit action=%i", s->start_limit_action);
|
||||
assert_not_reached("Unknown StartLimitAction.");
|
||||
}
|
||||
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
static int service_start(Unit *u) {
|
||||
Service *s = SERVICE(u);
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
@ -2348,10 +2398,9 @@ static int service_start(Unit *u) {
|
||||
assert(s->state == SERVICE_DEAD || s->state == SERVICE_FAILED || s->state == SERVICE_AUTO_RESTART);
|
||||
|
||||
/* Make sure we don't enter a busy loop of some kind. */
|
||||
if (!ratelimit_test(&s->ratelimit)) {
|
||||
log_warning("%s start request repeated too quickly, refusing to start.", u->id);
|
||||
return -ECANCELED;
|
||||
}
|
||||
r = service_start_limit_test(s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
s->result = SERVICE_SUCCESS;
|
||||
s->reload_result = SERVICE_SUCCESS;
|
||||
@ -3665,6 +3714,14 @@ static const char* const service_result_table[_SERVICE_RESULT_MAX] = {
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(service_result, ServiceResult);
|
||||
|
||||
static const char* const start_limit_action_table[_SERVICE_START_LIMIT_MAX] = {
|
||||
[SERVICE_START_LIMIT_NONE] = "none",
|
||||
[SERVICE_START_LIMIT_REBOOT] = "reboot",
|
||||
[SERVICE_START_LIMIT_REBOOT_FORCE] = "reboot-force",
|
||||
[SERVICE_START_LIMIT_REBOOT_IMMEDIATE] = "reboot-immediate"
|
||||
};
|
||||
DEFINE_STRING_TABLE_LOOKUP(start_limit_action, StartLimitAction);
|
||||
|
||||
const UnitVTable service_vtable = {
|
||||
.suffix = ".service",
|
||||
.object_size = sizeof(Service),
|
||||
|
@ -100,6 +100,15 @@ typedef enum ServiceResult {
|
||||
_SERVICE_RESULT_INVALID = -1
|
||||
} ServiceResult;
|
||||
|
||||
typedef enum StartLimitAction {
|
||||
SERVICE_START_LIMIT_NONE,
|
||||
SERVICE_START_LIMIT_REBOOT,
|
||||
SERVICE_START_LIMIT_REBOOT_FORCE,
|
||||
SERVICE_START_LIMIT_REBOOT_IMMEDIATE,
|
||||
_SERVICE_START_LIMIT_MAX,
|
||||
_SERVICE_START_LIMIT_INVALID = -1
|
||||
} StartLimitAction;
|
||||
|
||||
struct Service {
|
||||
Unit meta;
|
||||
|
||||
@ -169,7 +178,9 @@ struct Service {
|
||||
|
||||
char *status_text;
|
||||
|
||||
RateLimit ratelimit;
|
||||
RateLimit start_limit;
|
||||
StartLimitAction start_limit_action;
|
||||
|
||||
|
||||
UnitRef accept_socket;
|
||||
|
||||
@ -203,4 +214,7 @@ NotifyAccess notify_access_from_string(const char *s);
|
||||
const char* service_result_to_string(ServiceResult i);
|
||||
ServiceResult service_result_from_string(const char *s);
|
||||
|
||||
const char* start_limit_action_to_string(StartLimitAction i);
|
||||
StartLimitAction start_limit_action_from_string(const char *s);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user