|
|
7e7c9f |
From 909d27fffffb28f4da7752be25e5c47990eba641 Mon Sep 17 00:00:00 2001
|
|
|
7e7c9f |
From: Lennart Poettering <lennart@poettering.net>
|
|
|
7e7c9f |
Date: Mon, 13 Nov 2017 17:14:07 +0100
|
|
|
7e7c9f |
Subject: [PATCH] core: add a new unit file setting CollectMode= for tweaking
|
|
|
7e7c9f |
the GC logic
|
|
|
7e7c9f |
|
|
|
7e7c9f |
Right now, the option only takes one of two possible values "inactive"
|
|
|
7e7c9f |
or "inactive-or-failed", the former being the default, and exposing same
|
|
|
7e7c9f |
behaviour as the status quo ante. If set to "inactive-or-failed" units
|
|
|
7e7c9f |
may be collected by the GC logic when in the "failed" state too.
|
|
|
7e7c9f |
|
|
|
7e7c9f |
This logic should be a nicer alternative to using the "-" modifier for
|
|
|
7e7c9f |
ExecStart= and friends, as the exit data is collected and logged about
|
|
|
7e7c9f |
and only removed when the GC comes along. This should be useful in
|
|
|
7e7c9f |
particular for per-connection socket-activated services, as well as
|
|
|
7e7c9f |
"systemd-run" command lines that shall leave no artifacts in the
|
|
|
7e7c9f |
system.
|
|
|
7e7c9f |
|
|
|
7e7c9f |
I was thinking about whether to expose this as a boolean, but opted for
|
|
|
7e7c9f |
an enum instead, as I have the suspicion other tweaks like this might be
|
|
|
7e7c9f |
a added later on, in which case we extend this setting instead of having
|
|
|
7e7c9f |
to add yet another one.
|
|
|
7e7c9f |
|
|
|
7e7c9f |
Also, let's add some documentation for the GC logic.
|
|
|
7e7c9f |
|
|
|
7e7c9f |
(cherry-picked from commit 5afe510c89f26b0e721b276a0e78af914b47f0b0)
|
|
|
7e7c9f |
|
|
|
7e7c9f |
Resolves: #1817576
|
|
|
7e7c9f |
---
|
|
|
7e7c9f |
man/systemd.unit.xml | 56 +++++++++++++++++++++++++++
|
|
|
7e7c9f |
src/core/dbus-unit.c | 20 ++++++++++
|
|
|
7e7c9f |
src/core/load-fragment-gperf.gperf.m4 | 1 +
|
|
|
7e7c9f |
src/core/load-fragment.c | 2 +
|
|
|
7e7c9f |
src/core/load-fragment.h | 1 +
|
|
|
7e7c9f |
src/core/unit.c | 36 ++++++++++++++---
|
|
|
7e7c9f |
src/core/unit.h | 13 +++++++
|
|
|
7e7c9f |
7 files changed, 124 insertions(+), 5 deletions(-)
|
|
|
7e7c9f |
|
|
|
7e7c9f |
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
|
|
|
7e7c9f |
index 414749bae9..0c06add166 100644
|
|
|
7e7c9f |
--- a/man/systemd.unit.xml
|
|
|
7e7c9f |
+++ b/man/systemd.unit.xml
|
|
|
7e7c9f |
@@ -303,6 +303,45 @@
|
|
|
7e7c9f |
</para>
|
|
|
7e7c9f |
</refsect1>
|
|
|
7e7c9f |
|
|
|
7e7c9f |
+ <refsect1>
|
|
|
7e7c9f |
+ <title>Unit Garbage Collection</title>
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ <para>The system and service manager loads a unit's configuration automatically when a unit is referenced for the
|
|
|
7e7c9f |
+ first time. It will automatically unload the unit configuration and state again when the unit is not needed anymore
|
|
|
7e7c9f |
+ ("garbage collection"). A unit may be referenced through a number of different mechanisms:</para>
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ <orderedlist>
|
|
|
7e7c9f |
+ <listitem><para>Another loaded unit references it with a dependency such as <varname>After=</varname>,
|
|
|
7e7c9f |
+ <varname>Wants=</varname>, …</para></listitem>
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ <listitem><para>The unit is currently starting, running, reloading or stopping.</para></listitem>
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ <listitem><para>The unit is currently in the <constant>failed</constant> state. (But see below.)</para></listitem>
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ <listitem><para>A job for the unit is pending.</para></listitem>
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ <listitem><para>The unit is pinned by an active IPC client program.</para></listitem>
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ <listitem><para>The unit is a special "perpetual" unit that is always active and loaded. Examples for perpetual
|
|
|
7e7c9f |
+ units are the root mount unit <filename>-.mount</filename> or the scope unit <filename>init.scope</filename> that
|
|
|
7e7c9f |
+ the service manager itself lives in.</para></listitem>
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ <listitem><para>The unit has running processes associated with it.</para></listitem>
|
|
|
7e7c9f |
+ </orderedlist>
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ <para>The garbage collection logic may be altered with the <varname>CollectMode=</varname> option, which allows
|
|
|
7e7c9f |
+ configuration whether automatic unloading of units that are in <constant>failed</constant> state is permissible,
|
|
|
7e7c9f |
+ see below.</para>
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ <para>Note that when a unit's configuration and state is unloaded, all execution results, such as exit codes, exit
|
|
|
7e7c9f |
+ signals, resource consumption and other statistics are lost, except for what is stored in the log subsystem.</para>
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ <para>Use <command>systemctl daemon-reload</command> or an equivalent command to reload unit configuration while
|
|
|
7e7c9f |
+ the unit is already loaded. In this case all configuration settings are flushed out and replaced with the new
|
|
|
7e7c9f |
+ configuration (which however might not be in effect immediately), however all runtime state is
|
|
|
7e7c9f |
+ saved/restored.</para>
|
|
|
7e7c9f |
+ </refsect1>
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
<refsect1>
|
|
|
7e7c9f |
<title>[Unit] Section Options</title>
|
|
|
7e7c9f |
|
|
|
7e7c9f |
@@ -666,6 +705,23 @@
|
|
|
7e7c9f |
ones.</para></listitem>
|
|
|
7e7c9f |
</varlistentry>
|
|
|
7e7c9f |
|
|
|
7e7c9f |
+ <varlistentry>
|
|
|
7e7c9f |
+ <term><varname>CollectMode=</varname></term>
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ <listitem><para>Tweaks the "garbage collection" algorithm for this unit. Takes one of <option>inactive</option>
|
|
|
7e7c9f |
+ or <option>inactive-or-failed</option>. If set to <option>inactive</option> the unit will be unloaded if it is
|
|
|
7e7c9f |
+ in the <constant>inactive</constant> state and is not referenced by clients, jobs or other units — however it
|
|
|
7e7c9f |
+ is not unloaded if it is in the <constant>failed</constant> state. In <option>failed</option> mode, failed
|
|
|
7e7c9f |
+ units are not unloaded until the user invoked <command>systemctl reset-failed</command> on them to reset the
|
|
|
7e7c9f |
+ <constant>failed</constant> state, or an equivalent command. This behaviour is altered if this option is set to
|
|
|
7e7c9f |
+ <option>inactive-or-failed</option>: in this case the unit is unloaded even if the unit is in a
|
|
|
7e7c9f |
+ <constant>failed</constant> state, and thus an explicitly resetting of the <constant>failed</constant> state is
|
|
|
7e7c9f |
+ not necessary. Note that if this mode is used unit results (such as exit codes, exit signals, consumed
|
|
|
7e7c9f |
+ resources, …) are flushed out immediately after the unit completed, except for what is stored in the logging
|
|
|
7e7c9f |
+ subsystem. Defaults to <option>inactive</option>.</para>
|
|
|
7e7c9f |
+ </listitem>
|
|
|
7e7c9f |
+ </varlistentry>
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
<varlistentry>
|
|
|
7e7c9f |
<term><varname>JobTimeoutSec=</varname></term>
|
|
|
7e7c9f |
<term><varname>JobTimeoutAction=</varname></term>
|
|
|
7e7c9f |
diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c
|
|
|
7e7c9f |
index 77073308c8..ea6ac6767f 100644
|
|
|
7e7c9f |
--- a/src/core/dbus-unit.c
|
|
|
7e7c9f |
+++ b/src/core/dbus-unit.c
|
|
|
7e7c9f |
@@ -34,6 +34,7 @@
|
|
|
7e7c9f |
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_load_state, unit_load_state, UnitLoadState);
|
|
|
7e7c9f |
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_job_mode, job_mode, JobMode);
|
|
|
7e7c9f |
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
|
|
|
7e7c9f |
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_collect_mode, collect_mode, CollectMode);
|
|
|
7e7c9f |
|
|
|
7e7c9f |
static int property_get_names(
|
|
|
7e7c9f |
sd_bus *bus,
|
|
|
7e7c9f |
@@ -605,6 +606,7 @@ const sd_bus_vtable bus_unit_vtable[] = {
|
|
|
7e7c9f |
SD_BUS_PROPERTY("Asserts", "a(sbbsi)", property_get_conditions, offsetof(Unit, asserts), 0),
|
|
|
7e7c9f |
SD_BUS_PROPERTY("LoadError", "(ss)", property_get_load_error, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
7e7c9f |
SD_BUS_PROPERTY("Transient", "b", bus_property_get_bool, offsetof(Unit, transient), SD_BUS_VTABLE_PROPERTY_CONST),
|
|
|
7e7c9f |
+ SD_BUS_PROPERTY("CollectMode", "s", property_get_collect_mode, offsetof(Unit, collect_mode), 0),
|
|
|
7e7c9f |
|
|
|
7e7c9f |
SD_BUS_METHOD("Start", "s", "o", method_start, 0),
|
|
|
7e7c9f |
SD_BUS_METHOD("Stop", "s", "o", method_stop, 0),
|
|
|
7e7c9f |
@@ -937,6 +939,24 @@ static int bus_unit_set_transient_property(
|
|
|
7e7c9f |
|
|
|
7e7c9f |
return 1;
|
|
|
7e7c9f |
|
|
|
7e7c9f |
+ } else if (streq(name, "CollectMode")) {
|
|
|
7e7c9f |
+ const char *s;
|
|
|
7e7c9f |
+ CollectMode m;
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ r = sd_bus_message_read(message, "s", &s);
|
|
|
7e7c9f |
+ if (r < 0)
|
|
|
7e7c9f |
+ return r;
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ m = collect_mode_from_string(s);
|
|
|
7e7c9f |
+ if (m < 0)
|
|
|
7e7c9f |
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown garbage collection mode: %s", s);
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ if (mode != UNIT_CHECK) {
|
|
|
7e7c9f |
+ u->collect_mode = m;
|
|
|
7e7c9f |
+ unit_write_drop_in_format(u, mode, name, "[Unit]\nCollectMode=%s", collect_mode_to_string(m));
|
|
|
7e7c9f |
+ }
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ return 1;
|
|
|
7e7c9f |
} else if (streq(name, "Slice") && unit_get_cgroup_context(u)) {
|
|
|
7e7c9f |
const char *s;
|
|
|
7e7c9f |
|
|
|
7e7c9f |
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
|
|
|
7e7c9f |
index 664bba0ef6..3a8ee96fa3 100644
|
|
|
7e7c9f |
--- a/src/core/load-fragment-gperf.gperf.m4
|
|
|
7e7c9f |
+++ b/src/core/load-fragment-gperf.gperf.m4
|
|
|
7e7c9f |
@@ -200,6 +200,7 @@ Unit.AssertCapability, config_parse_unit_condition_string, CONDITION_C
|
|
|
7e7c9f |
Unit.AssertHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, asserts)
|
|
|
7e7c9f |
Unit.AssertACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, asserts)
|
|
|
7e7c9f |
Unit.AssertNull, config_parse_unit_condition_null, 0, offsetof(Unit, asserts)
|
|
|
7e7c9f |
+Unit.CollectMode, config_parse_collect_mode, 0, offsetof(Unit, collect_mode)
|
|
|
7e7c9f |
m4_dnl
|
|
|
7e7c9f |
Service.PIDFile, config_parse_unit_path_printf, 0, offsetof(Service, pid_file)
|
|
|
7e7c9f |
Service.ExecStartPre, config_parse_exec, SERVICE_EXEC_START_PRE, offsetof(Service, exec_command)
|
|
|
7e7c9f |
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
|
|
|
7e7c9f |
index 1721fea8f3..8d73d5df41 100644
|
|
|
7e7c9f |
--- a/src/core/load-fragment.c
|
|
|
7e7c9f |
+++ b/src/core/load-fragment.c
|
|
|
7e7c9f |
@@ -98,6 +98,8 @@ int config_parse_warn_compat(
|
|
|
7e7c9f |
return 0;
|
|
|
7e7c9f |
}
|
|
|
7e7c9f |
|
|
|
7e7c9f |
+DEFINE_CONFIG_PARSE_ENUM(config_parse_collect_mode, collect_mode, CollectMode, "Failed to parse garbage collection mode");
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
int config_parse_unit_deps(const char *unit,
|
|
|
7e7c9f |
const char *filename,
|
|
|
7e7c9f |
unsigned line,
|
|
|
7e7c9f |
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
|
|
|
7e7c9f |
index 4bd286c11b..7b1193ddb2 100644
|
|
|
7e7c9f |
--- a/src/core/load-fragment.h
|
|
|
7e7c9f |
+++ b/src/core/load-fragment.h
|
|
|
7e7c9f |
@@ -110,6 +110,7 @@ int config_parse_cpu_quota(const char *unit, const char *filename, unsigned line
|
|
|
7e7c9f |
int config_parse_protect_home(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
|
|
7e7c9f |
int config_parse_protect_system(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
|
|
7e7c9f |
int config_parse_bus_name(const char* unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
|
|
7e7c9f |
+int config_parse_collect_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
|
|
7e7c9f |
|
|
|
7e7c9f |
/* gperf prototypes */
|
|
|
7e7c9f |
const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
|
|
|
7e7c9f |
diff --git a/src/core/unit.c b/src/core/unit.c
|
|
|
7e7c9f |
index eff9fdbe70..502830d2cb 100644
|
|
|
7e7c9f |
--- a/src/core/unit.c
|
|
|
7e7c9f |
+++ b/src/core/unit.c
|
|
|
7e7c9f |
@@ -67,7 +67,7 @@ const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = {
|
|
|
7e7c9f |
[UNIT_TIMER] = &timer_vtable,
|
|
|
7e7c9f |
[UNIT_PATH] = &path_vtable,
|
|
|
7e7c9f |
[UNIT_SLICE] = &slice_vtable,
|
|
|
7e7c9f |
- [UNIT_SCOPE] = &scope_vtable
|
|
|
7e7c9f |
+ [UNIT_SCOPE] = &scope_vtable,
|
|
|
7e7c9f |
};
|
|
|
7e7c9f |
|
|
|
7e7c9f |
static int maybe_warn_about_dependency(const char *id, const char *other, UnitDependency dependency);
|
|
|
7e7c9f |
@@ -285,6 +285,7 @@ int unit_set_description(Unit *u, const char *description) {
|
|
|
7e7c9f |
|
|
|
7e7c9f |
bool unit_may_gc(Unit *u) {
|
|
|
7e7c9f |
UnitActiveState state;
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
assert(u);
|
|
|
7e7c9f |
|
|
|
7e7c9f |
/* Checks whether the unit is ready to be unloaded for garbage collection.
|
|
|
7e7c9f |
@@ -308,16 +309,31 @@ bool unit_may_gc(Unit *u) {
|
|
|
7e7c9f |
UNIT_VTABLE(u)->release_resources)
|
|
|
7e7c9f |
UNIT_VTABLE(u)->release_resources(u);
|
|
|
7e7c9f |
|
|
|
7e7c9f |
- /* But we keep the unit object around for longer when it is referenced or configured to not be gc'ed */
|
|
|
7e7c9f |
- if (state != UNIT_INACTIVE)
|
|
|
7e7c9f |
- return false;
|
|
|
7e7c9f |
-
|
|
|
7e7c9f |
if (UNIT_VTABLE(u)->no_gc)
|
|
|
7e7c9f |
return false;
|
|
|
7e7c9f |
|
|
|
7e7c9f |
if (u->no_gc)
|
|
|
7e7c9f |
return false;
|
|
|
7e7c9f |
|
|
|
7e7c9f |
+ /* But we keep the unit object around for longer when it is referenced or configured to not be gc'ed */
|
|
|
7e7c9f |
+ switch (u->collect_mode) {
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ case COLLECT_INACTIVE:
|
|
|
7e7c9f |
+ if (state != UNIT_INACTIVE)
|
|
|
7e7c9f |
+ return false;
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ break;
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ case COLLECT_INACTIVE_OR_FAILED:
|
|
|
7e7c9f |
+ if (!IN_SET(state, UNIT_INACTIVE, UNIT_FAILED))
|
|
|
7e7c9f |
+ return false;
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ break;
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+ default:
|
|
|
7e7c9f |
+ assert_not_reached("Unknown garbage collection mode");
|
|
|
7e7c9f |
+ }
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
if (UNIT_VTABLE(u)->may_gc && !UNIT_VTABLE(u)->may_gc(u))
|
|
|
7e7c9f |
return false;
|
|
|
7e7c9f |
|
|
|
7e7c9f |
@@ -896,6 +912,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
|
|
|
7e7c9f |
"%s\tMay GC: %s\n"
|
|
|
7e7c9f |
"%s\tNeed Daemon Reload: %s\n"
|
|
|
7e7c9f |
"%s\tTransient: %s\n"
|
|
|
7e7c9f |
+ "%s\tGarbage Collection Mode: %s\n"
|
|
|
7e7c9f |
"%s\tSlice: %s\n"
|
|
|
7e7c9f |
"%s\tCGroup: %s\n"
|
|
|
7e7c9f |
"%s\tCGroup realized: %s\n"
|
|
|
7e7c9f |
@@ -913,6 +930,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
|
|
|
7e7c9f |
prefix, yes_no(unit_may_gc(u)),
|
|
|
7e7c9f |
prefix, yes_no(unit_need_daemon_reload(u)),
|
|
|
7e7c9f |
prefix, yes_no(u->transient),
|
|
|
7e7c9f |
+ prefix, collect_mode_to_string(u->collect_mode),
|
|
|
7e7c9f |
prefix, strna(unit_slice_name(u)),
|
|
|
7e7c9f |
prefix, strna(u->cgroup_path),
|
|
|
7e7c9f |
prefix, yes_no(u->cgroup_realized),
|
|
|
7e7c9f |
@@ -3732,3 +3750,11 @@ static const char* const unit_active_state_table[_UNIT_ACTIVE_STATE_MAX] = {
|
|
|
7e7c9f |
};
|
|
|
7e7c9f |
|
|
|
7e7c9f |
DEFINE_STRING_TABLE_LOOKUP(unit_active_state, UnitActiveState);
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+static const char* const collect_mode_table[_COLLECT_MODE_MAX] = {
|
|
|
7e7c9f |
+ [COLLECT_INACTIVE] = "inactive",
|
|
|
7e7c9f |
+ [COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed",
|
|
|
7e7c9f |
+};
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
+DEFINE_STRING_TABLE_LOOKUP(collect_mode, CollectMode);
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
diff --git a/src/core/unit.h b/src/core/unit.h
|
|
|
7e7c9f |
index 3b0fd8d9df..8cc7a9e0b2 100644
|
|
|
7e7c9f |
--- a/src/core/unit.h
|
|
|
7e7c9f |
+++ b/src/core/unit.h
|
|
|
7e7c9f |
@@ -60,6 +60,13 @@ typedef enum KillOperation {
|
|
|
7e7c9f |
KILL_ABORT,
|
|
|
7e7c9f |
} KillOperation;
|
|
|
7e7c9f |
|
|
|
7e7c9f |
+typedef enum CollectMode {
|
|
|
7e7c9f |
+ COLLECT_INACTIVE,
|
|
|
7e7c9f |
+ COLLECT_INACTIVE_OR_FAILED,
|
|
|
7e7c9f |
+ _COLLECT_MODE_MAX,
|
|
|
7e7c9f |
+ _COLLECT_MODE_INVALID = -1,
|
|
|
7e7c9f |
+} CollectMode;
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
static inline bool UNIT_IS_ACTIVE_OR_RELOADING(UnitActiveState t) {
|
|
|
7e7c9f |
return t == UNIT_ACTIVE || t == UNIT_RELOADING;
|
|
|
7e7c9f |
}
|
|
|
7e7c9f |
@@ -198,6 +205,9 @@ struct Unit {
|
|
|
7e7c9f |
/* How to start OnFailure units */
|
|
|
7e7c9f |
JobMode on_failure_job_mode;
|
|
|
7e7c9f |
|
|
|
7e7c9f |
+ /* Tweaking the GC logic */
|
|
|
7e7c9f |
+ CollectMode collect_mode;
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
/* Garbage collect us we nobody wants or requires us anymore */
|
|
|
7e7c9f |
bool stop_when_unneeded;
|
|
|
7e7c9f |
|
|
|
7e7c9f |
@@ -630,6 +640,9 @@ pid_t unit_main_pid(Unit *u);
|
|
|
7e7c9f |
const char *unit_active_state_to_string(UnitActiveState i) _const_;
|
|
|
7e7c9f |
UnitActiveState unit_active_state_from_string(const char *s) _pure_;
|
|
|
7e7c9f |
|
|
|
7e7c9f |
+const char* collect_mode_to_string(CollectMode m) _const_;
|
|
|
7e7c9f |
+CollectMode collect_mode_from_string(const char *s) _pure_;
|
|
|
7e7c9f |
+
|
|
|
7e7c9f |
bool unit_needs_console(Unit *u);
|
|
|
7e7c9f |
|
|
|
7e7c9f |
/* Macros which append UNIT= or USER_UNIT= to the message */
|