From 03854532d39613723dc8b85c424737ecf2e46f74 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 16 Apr 2012 18:54:45 +0200 Subject: [PATCH 1/3] util: introduce memdup() --- src/util.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/src/util.h b/src/util.h index b1af6db..06c9933 100644 --- a/src/util.h +++ b/src/util.h @@ -99,6 +99,8 @@ bool streq_ptr(const char *a, const char *b); #define new0(t, n) ((t*) calloc((n), sizeof(t))) +#define newdup(t, p, n) ((t*) memdup(p, sizeof(t)*(n)) + #define malloc0(n) (calloc((n), 1)) static inline const char* yes_no(bool b) { -- 1.7.7 From f60b5d436f502152415b08758737f200113ce4bc Mon Sep 17 00:00:00 2001 From: Frederic Crozat Date: Mon, 21 May 2012 16:53:18 +0200 Subject: [PATCH 2/3] util: fix typo in newdup Conflicts: src/util.h --- src/util.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/src/util.h b/src/util.h index 06c9933..41b4c9f 100644 --- a/src/util.h +++ b/src/util.h @@ -99,7 +99,7 @@ bool streq_ptr(const char *a, const char *b); #define new0(t, n) ((t*) calloc((n), sizeof(t))) -#define newdup(t, p, n) ((t*) memdup(p, sizeof(t)*(n)) +#define newdup(t, p, n) ((t*) memdup(p, sizeof(t)*(n))) #define malloc0(n) (calloc((n), 1)) -- 1.7.7 From 8e7fa2b3e68b691c522cf2b60ed920452c146c2e Mon Sep 17 00:00:00 2001 From: Frederic Crozat Date: Wed, 27 Jun 2012 14:12:44 +0200 Subject: [PATCH 3/3] main: allow system wide limits for services --- man/systemd.conf.xml | 27 +++++++++++++++++++++++++++ src/main.c | 22 ++++++++++++++++++++++ src/manager.c | 22 ++++++++++++++++++++++ src/manager.h | 3 +++ src/service.c | 4 ++++ 5 files changed, 78 insertions(+), 0 deletions(-) diff --git a/man/systemd.conf.xml b/man/systemd.conf.xml index ba144da..ee461e3 100644 --- a/man/systemd.conf.xml +++ b/man/systemd.conf.xml @@ -149,6 +149,33 @@ controllers in separate hierarchies. + + + DefaultLimitCPU= + DefaultLimitFSIZE= + DefaultLimitDATA= + DefaultLimitSTACK= + DefaultLimitCORE= + DefaultLimitRSS= + DefaultLimitNOFILE= + DefaultLimitAS= + DefaultLimitNPROC= + DefaultLimitMEMLOCK= + DefaultLimitLOCKS= + DefaultLimitSIGPENDING= + DefaultLimitMSGQUEUE= + DefaultLimitNICE= + DefaultLimitRTPRIO= + DefaultLimitRTTIME= + These settings control + various default resource limits for units. See + setrlimit2 + for details. Use the string + infinity to + configure no limit on a specific + resource. They can be overriden in units files + using corresponding LimitXXXX parameter. + diff --git a/src/main.c b/src/main.c index ed317b4..3f5f3d7 100644 --- a/src/main.c +++ b/src/main.c @@ -79,6 +79,7 @@ static char **arg_default_controllers = NULL; static char ***arg_join_controllers = NULL; static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL; static ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT; +static struct rlimit *arg_default_rlimit[RLIMIT_NLIMITS] = {}; static FILE* serialization = NULL; @@ -659,6 +660,22 @@ static int parse_config_file(void) { { "Manager", "DefaultStandardOutput", config_parse_output, 0, &arg_default_std_output }, { "Manager", "DefaultStandardError", config_parse_output, 0, &arg_default_std_error }, { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers }, + { "Manager", "DefaultLimitCPU", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CPU]}, + { "Manager", "DefaultLimitFSIZE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_FSIZE]}, + { "Manager", "DefaultLimitDATA", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_DATA]}, + { "Manager", "DefaultLimitSTACK", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_STACK]}, + { "Manager", "DefaultLimitCORE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CORE]}, + { "Manager", "DefaultLimitRSS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RSS]}, + { "Manager", "DefaultLimitNOFILE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NOFILE]}, + { "Manager", "DefaultLimitAS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_AS]}, + { "Manager", "DefaultLimitNPROC", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NPROC]}, + { "Manager", "DefaultLimitMEMLOCK", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_MEMLOCK]}, + { "Manager", "DefaultLimitLOCKS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_LOCKS]}, + { "Manager", "DefaultLimitSIGPENDING",config_parse_limit, 0, &arg_default_rlimit[RLIMIT_SIGPENDING]}, + { "Manager", "DefaultLimitMSGQUEUE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_MSGQUEUE]}, + { "Manager", "DefaultLimitNICE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NICE]}, + { "Manager", "DefaultLimitRTPRIO", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTPRIO]}, + { "Manager", "DefaultLimitRTTIME", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTTIME]}, { NULL, NULL, NULL, 0, NULL } }; @@ -1401,6 +1418,8 @@ int main(int argc, char *argv[]) { m->default_std_output = arg_default_std_output; m->default_std_error = arg_default_std_error; + manager_set_default_rlimits(m, arg_default_rlimit); + if (dual_timestamp_is_set(&initrd_timestamp)) m->initrd_timestamp = initrd_timestamp; @@ -1539,6 +1558,9 @@ finish: if (m) manager_free(m); + for (j = 0; j < RLIMIT_NLIMITS; j++) + free (arg_default_rlimit[j]); + free(arg_default_unit); strv_free(arg_default_controllers); free_join_controllers(); diff --git a/src/manager.c b/src/manager.c index 3e592b6..c6cd06c 100644 --- a/src/manager.c +++ b/src/manager.c @@ -456,6 +456,7 @@ static void manager_clear_jobs_and_units(Manager *m) { void manager_free(Manager *m) { UnitType c; + int i; assert(m); @@ -501,6 +502,9 @@ void manager_free(Manager *m) { hashmap_free(m->cgroup_bondings); set_free_free(m->unit_path_cache); + for (i = 0; i < RLIMIT_NLIMITS; i++) + free(m->rlimit[i]); + free(m); } @@ -3137,6 +3141,24 @@ int manager_set_default_controllers(Manager *m, char **controllers) { return 0; } +int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit) { + int i; + + assert(m); + + for (i = 0; i < RLIMIT_NLIMITS; i++) { + if (default_rlimit[i]) { + m->rlimit[i] = newdup(struct rlimit, default_rlimit[i], 1); + + if (!m->rlimit[i]) + return -ENOMEM; + } + } + + return 0; +} + + void manager_recheck_journal(Manager *m) { Unit *u; diff --git a/src/manager.h b/src/manager.h index a9d08f0..5f5de8e 100644 --- a/src/manager.h +++ b/src/manager.h @@ -225,6 +225,8 @@ struct Manager { ExecOutput default_std_output, default_std_error; + struct rlimit *rlimit[RLIMIT_NLIMITS]; + /* non-zero if we are reloading or reexecuting, */ int n_reloading; @@ -263,6 +265,7 @@ unsigned manager_dispatch_run_queue(Manager *m); unsigned manager_dispatch_dbus_queue(Manager *m); int manager_set_default_controllers(Manager *m, char **controllers); +int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit); int manager_loop(Manager *m); diff --git a/src/service.c b/src/service.c index 8b5c0b0..892392d 100644 --- a/src/service.c +++ b/src/service.c @@ -109,6 +109,7 @@ static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = { static void service_init(Unit *u) { Service *s = SERVICE(u); + int i; assert(u); assert(u->load_state == UNIT_STUB); @@ -127,6 +128,9 @@ static void service_init(Unit *u) { s->guess_main_pid = true; exec_context_init(&s->exec_context); + for (i = 0; i < RLIMIT_NLIMITS; i++) + if (UNIT(s)->manager->rlimit[i]) + s->exec_context.rlimit[i] = newdup(struct rlimit, UNIT(s)->manager->rlimit[i], 1); RATELIMIT_INIT(s->start_limit, 10*USEC_PER_SEC, 5); -- 1.7.7