#include "sd-id128.h"
#include "bpf-program.h"
+#include "cgroup.h"
#include "condition.h"
#include "emergency-action.h"
+#include "install.h"
#include "list.h"
-#include "show-status.h"
+#include "pidref.h"
#include "set.h"
+#include "show-status.h"
#include "unit-file.h"
-#include "cgroup.h"
typedef struct UnitRef UnitRef;
/* Queue of units that have a BindTo= dependency on some other unit, and should possibly be shut down */
LIST_FIELDS(Unit, stop_when_bound_queue);
+ /* Queue of units that should be checked if they can release resources now */
+ LIST_FIELDS(Unit, release_resources_queue);
+
/* PIDs we keep an eye on. Note that a unit might have many
* more, but these are the ones we care enough about to
* process SIGCHLD for */
/* Make sure we never enter endless loops with the StopWhenUnneeded=, BindsTo=, Uphold= logic */
RateLimit auto_start_stop_ratelimit;
+ sd_event_source *auto_start_stop_event_source;
/* Reference to a specific UID/GID */
uid_t ref_uid;
/* Cached unit file state and preset */
UnitFileState unit_file_state;
- int unit_file_preset;
+ PresetAction unit_file_preset;
/* Where the cpu.stat or cpuacct.usage was at the time the unit was started */
nsec_t cpu_usage_base;
bool in_stop_when_unneeded_queue:1;
bool in_start_when_upheld_queue:1;
bool in_stop_when_bound_queue:1;
+ bool in_release_resources_queue:1;
bool sent_dbus_new_signal:1;
/* Flags used when writing drop-in files or transient unit files */
typedef enum UnitWriteFlags {
/* Write a runtime unit file or drop-in (i.e. one below /run) */
- UNIT_RUNTIME = 1 << 0,
+ UNIT_RUNTIME = 1 << 0,
/* Write a persistent drop-in (i.e. one below /etc) */
- UNIT_PERSISTENT = 1 << 1,
+ UNIT_PERSISTENT = 1 << 1,
/* Place this item in the per-unit-type private section, instead of [Unit] */
- UNIT_PRIVATE = 1 << 2,
+ UNIT_PRIVATE = 1 << 2,
+
+ /* Apply specifier escaping */
+ UNIT_ESCAPE_SPECIFIERS = 1 << 3,
- /* Apply specifier escaping before writing */
- UNIT_ESCAPE_SPECIFIERS = 1 << 3,
+ /* Escape elements of ExecStart= syntax, incl. prevention of variable expansion */
+ UNIT_ESCAPE_EXEC_SYNTAX_ENV = 1 << 4,
- /* Escape elements of ExecStart= syntax before writing */
- UNIT_ESCAPE_EXEC_SYNTAX = 1 << 4,
+ /* Escape elements of ExecStart=: syntax (no variable expansion) */
+ UNIT_ESCAPE_EXEC_SYNTAX = 1 << 5,
/* Apply C escaping before writing */
- UNIT_ESCAPE_C = 1 << 5,
+ UNIT_ESCAPE_C = 1 << 6,
} UnitWriteFlags;
/* Returns true if neither persistent, nor runtime storage is requested, i.e. this is a check invocation only */
size_t kill_context_offset;
/* If greater than 0, the offset into the object where the
- * pointer to ExecRuntime is found, if the unit type has
+ * pointer to ExecSharedRuntime is found, if the unit type has
* that */
size_t exec_runtime_offset;
- /* If greater than 0, the offset into the object where the pointer to DynamicCreds is found, if the unit type
- * has that. */
- size_t dynamic_creds_offset;
-
/* The name of the configuration file section with the private settings of this unit */
const char *private_section;
int (*stop)(Unit *u);
int (*reload)(Unit *u);
- int (*kill)(Unit *u, KillWho w, int signo, int code, int value, sd_bus_error *error);
-
/* Clear out the various runtime/state/cache/logs/configuration data */
int (*clean)(Unit *u, ExecCleanMask m);
/* Returns the next timeout of a unit */
int (*get_timeout)(Unit *u, usec_t *timeout);
- /* Returns the main PID if there is any defined, or 0. */
- pid_t (*main_pid)(Unit *u);
+ /* Returns the start timeout of a unit */
+ usec_t (*get_timeout_start_usec)(Unit *u);
/* Returns the main PID if there is any defined, or 0. */
- pid_t (*control_pid)(Unit *u);
+ PidRef* (*main_pid)(Unit *u);
+
+ /* Returns the control PID if there is any defined, or 0. */
+ PidRef* (*control_pid)(Unit *u);
/* Returns true if the unit currently needs access to the console */
bool (*needs_console)(Unit *u);
* limiting checks to occur before we do anything else. */
int (*can_start)(Unit *u);
+ /* Returns > 0 if the whole subsystem is ratelimited, and new start operations should not be started
+ * for this unit type right now. */
+ int (*subsystem_ratelimited)(Manager *m);
+
/* The strings to print in status messages */
UnitStatusMessageFormats status_message_formats;
/* True if systemd-oomd can monitor and act on this unit's recursive children's cgroups */
bool can_set_managed_oom;
+
+ /* If true, we'll notify plymouth about this unit */
+ bool notify_plymouth;
+
+ /* The audit events to generate on start + stop (or 0 if none shall be generated) */
+ int audit_start_message_type;
+ int audit_stop_message_type;
} UnitVTable;
extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX];
Unit* unit_has_dependency(const Unit *u, UnitDependencyAtom atom, Unit *other);
int unit_get_dependency_array(const Unit *u, UnitDependencyAtom atom, Unit ***ret_array);
+int unit_get_transitive_dependency_set(Unit *u, UnitDependencyAtom atom, Set **ret);
static inline Hashmap* unit_get_dependencies(Unit *u, UnitDependency d) {
return hashmap_get(u->dependencies, UNIT_DEPENDENCY_TO_PTR(d));
int unit_choose_id(Unit *u, const char *name);
int unit_set_description(Unit *u, const char *description);
+void unit_release_resources(Unit *u);
+
bool unit_may_gc(Unit *u);
static inline bool unit_is_extrinsic(Unit *u) {
void unit_submit_to_stop_when_unneeded_queue(Unit *u);
void unit_submit_to_start_when_upheld_queue(Unit *u);
void unit_submit_to_stop_when_bound_queue(Unit *u);
+void unit_submit_to_release_resources_queue(Unit *u);
int unit_merge(Unit *u, Unit *other);
int unit_merge_by_name(Unit *u, const char *other);
int unit_reload(Unit *u);
int unit_kill(Unit *u, KillWho w, int signo, int code, int value, sd_bus_error *error);
-int unit_kill_common(Unit *u, KillWho who, int signo, int code, int value, pid_t main_pid, pid_t control_pid, sd_bus_error *error);
void unit_notify_cgroup_oom(Unit *u, bool managed_oom);
-typedef enum UnitNotifyFlags {
- UNIT_NOTIFY_RELOAD_FAILURE = 1 << 0,
- UNIT_NOTIFY_WILL_AUTO_RESTART = 1 << 1,
-} UnitNotifyFlags;
-
-void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlags flags);
+void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_success);
int unit_watch_pid(Unit *u, pid_t pid, bool exclusive);
void unit_unwatch_pid(Unit *u, pid_t pid);
void unit_trigger_notify(Unit *u);
UnitFileState unit_get_unit_file_state(Unit *u);
-int unit_get_unit_file_preset(Unit *u);
+PresetAction unit_get_unit_file_preset(Unit *u);
Unit* unit_ref_set(UnitRef *ref, Unit *source, Unit *target);
void unit_ref_unset(UnitRef *ref);
ExecRuntime *unit_get_exec_runtime(Unit *u) _pure_;
int unit_setup_exec_runtime(Unit *u);
-int unit_setup_dynamic_creds(Unit *u);
-char* unit_escape_setting(const char *s, UnitWriteFlags flags, char **buf);
+const char* unit_escape_setting(const char *s, UnitWriteFlags flags, char **buf);
char* unit_concat_strv(char **l, UnitWriteFlags flags);
int unit_write_setting(Unit *u, UnitWriteFlags flags, const char *name, const char *data);
int unit_write_settingf(Unit *u, UnitWriteFlags mode, const char *name, const char *format, ...) _printf_(4,5);
-int unit_kill_context(Unit *u, KillContext *c, KillOperation k, pid_t main_pid, pid_t control_pid, bool main_pid_alien);
+int unit_kill_context(Unit *u, KillContext *c, KillOperation k, PidRef *main_pid, PidRef *control_pid, bool main_pid_alien);
int unit_make_transient(Unit *u);
bool unit_is_upheld_by_active(Unit *u, Unit **ret_culprit);
bool unit_is_bound_by_inactive(Unit *u, Unit **ret_culprit);
-pid_t unit_control_pid(Unit *u);
-pid_t unit_main_pid(Unit *u);
+PidRef* unit_control_pid(Unit *u);
+PidRef* unit_main_pid(Unit *u);
void unit_warn_if_dir_nonempty(Unit *u, const char* where);
int unit_fail_if_noncanonical(Unit *u, const char* where);
int unit_set_exec_params(Unit *s, ExecParameters *p);
-int unit_fork_helper_process(Unit *u, const char *name, pid_t *ret);
-int unit_fork_and_watch_rm_rf(Unit *u, char **paths, pid_t *ret_pid);
+int unit_fork_helper_process(Unit *u, const char *name, PidRef *ret);
+int unit_fork_and_watch_rm_rf(Unit *u, char **paths, PidRef *ret);
void unit_remove_dependencies(Unit *u, UnitDependencyMask mask);