Compare commits

..

No commits in common. "49d5aae503f86c61c9e8325c86494431fcf8ca98" and "9554b8d1d1203c6f2d3ad5315ffa95cfd7494f45" have entirely different histories.

28 changed files with 138 additions and 254 deletions

2
TODO
View File

@ -19,8 +19,6 @@ Janitorial Clean-ups:
Features: Features:
* if /usr/bin/swapoff fails due to OOM, log a friendly explanatory message about it
* build short web pages out of each catalog entry, build them along with man * build short web pages out of each catalog entry, build them along with man
pages, and include hyperlinks to them in the journal output pages, and include hyperlinks to them in the journal output

View File

@ -393,17 +393,18 @@
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><option>tmp=</option></term> <term><option>tmp</option></term>
<listitem><para>The encrypted block device will be prepared for using it as <listitem><para>The encrypted block device will be prepared
<filename>/tmp/</filename>; it will be formatted using <citerefentry for using it as <filename>/tmp</filename>; it will be
project='man-pages'><refentrytitle>mkfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>. Takes formatted using
a file system type as argument, such as <literal>ext4</literal>, <literal>xfs</literal> or <citerefentry project='man-pages'><refentrytitle>mke2fs</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
<literal>btrfs</literal>. If no argument is specified defaults to <literal>ext4</literal>. This This option implies <option>plain</option>.</para>
option implies <option>plain</option>.</para>
<para>WARNING: Using the <option>tmp</option> option will destroy the contents of the named partition <para>WARNING: Using the <option>tmp</option> option will
during every boot, so make sure the underlying block device is specified correctly.</para></listitem> destroy the contents of the named partition during every boot,
so make sure the underlying block device is specified
correctly.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>

View File

@ -61,25 +61,28 @@
<varlistentry> <varlistentry>
<term><varname>KillMode=</varname></term> <term><varname>KillMode=</varname></term>
<listitem><para>Specifies how processes of this unit shall be killed. One of <listitem><para>Specifies how processes of this unit shall be
<option>control-group</option>, <option>mixed</option>, <option>process</option>, killed. One of
<option>control-group</option>,
<option>process</option>,
<option>mixed</option>,
<option>none</option>.</para> <option>none</option>.</para>
<para>If set to <option>control-group</option>, all remaining processes in the control group of this <para>If set to <option>control-group</option>, all remaining
unit will be killed on unit stop (for services: after the stop command is executed, as configured processes in the control group of this unit will be killed on
with <varname>ExecStop=</varname>). If set to <option>mixed</option>, the unit stop (for services: after the stop command is executed,
<constant>SIGTERM</constant> signal (see below) is sent to the main process while the subsequent as configured with <varname>ExecStop=</varname>). If set to
<constant>SIGKILL</constant> signal (see below) is sent to all remaining processes of the unit's <option>process</option>, only the main process itself is
control group. If set to <option>process</option>, only the main process itself is killed (not killed. If set to <option>mixed</option>, the
recommended!). If set to <option>none</option>, no process is killed (strongly recommended <constant>SIGTERM</constant> signal (see below) is sent to the
against!). In this case, only the stop command will be executed on unit stop, but no process will be main process while the subsequent <constant>SIGKILL</constant>
killed otherwise. Processes remaining alive after stop are left in their control group and the signal (see below) is sent to all remaining processes of the
control group continues to exist after stop unless empty.</para> unit's control group. If set to <option>none</option>, no
process is killed. In this case, only the stop command will be
<para>Note that it is not recommended to set <varname>KillMode=</varname> to executed on unit stop, but no process will be killed otherwise.
<constant>process</constant> or even <constant>none</constant>, as this allows processes to escape Processes remaining alive after stop are left in their control
the service manager's lifecycle and resource management, and to remain running even while their group and the control group continues to exist after stop
service is considered stopped and is assumed to not consume any resources.</para> unless it is empty.</para>
<para>Processes will first be terminated via <constant>SIGTERM</constant> (unless the signal to send <para>Processes will first be terminated via <constant>SIGTERM</constant> (unless the signal to send
is changed via <varname>KillSignal=</varname> or <varname>RestartKillSignal=</varname>). Optionally, is changed via <varname>KillSignal=</varname> or <varname>RestartKillSignal=</varname>). Optionally,

View File

@ -1550,7 +1550,7 @@
already existing public-key cryptography, for post-quantum already existing public-key cryptography, for post-quantum
resistance. resistance.
Note that because this information is secret, you may want to set Note that because this information is secret, you may want to set
the permissions of the .netdev file to be owned by <literal>root:systemd-network</literal> the permissions of the .netdev file to be owned by <literal>root:systemd-networkd</literal>
with a <literal>0640</literal> file mode.</para> with a <literal>0640</literal> file mode.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -28,7 +28,6 @@ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, Servi
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction); static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
static BUS_DEFINE_PROPERTY_GET(property_get_timeout_abort_usec, "t", Service, service_timeout_abort_usec); static BUS_DEFINE_PROPERTY_GET(property_get_timeout_abort_usec, "t", Service, service_timeout_abort_usec);
static BUS_DEFINE_PROPERTY_GET(property_get_watchdog_usec, "t", Service, service_get_watchdog_usec);
static int property_get_exit_status_set( static int property_get_exit_status_set(
sd_bus *bus, sd_bus *bus,
@ -102,7 +101,7 @@ const sd_bus_vtable bus_service_vtable[] = {
SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TimeoutAbortUSec", "t", property_get_timeout_abort_usec, 0, 0), SD_BUS_PROPERTY("TimeoutAbortUSec", "t", property_get_timeout_abort_usec, 0, 0),
SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("WatchdogUSec", "t", property_get_watchdog_usec, 0, 0), SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0), BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), /* 😷 deprecated */ SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), /* 😷 deprecated */
SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST),

View File

@ -117,6 +117,7 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGrou
DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode, "Failed to parse keyring mode"); DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode, "Failed to parse keyring mode");
DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode, "Failed to parse utmp mode"); DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode, "Failed to parse utmp mode");
DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode"); DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier"); DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_home, protect_home, ProtectHome, "Failed to parse protect home value"); DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_home, protect_home, ProtectHome, "Failed to parse protect home value");
DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_system, protect_system, ProtectSystem, "Failed to parse protect system value"); DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_system, protect_system, ProtectSystem, "Failed to parse protect system value");
@ -630,48 +631,6 @@ int config_parse_exec_coredump_filter(
return 0; return 0;
} }
int config_parse_kill_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) {
KillMode *k = data, m;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
*k = KILL_CONTROL_GROUP;
return 0;
}
m = kill_mode_from_string(rvalue);
if (m < 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Failed to parse kill mode specification, ignoring: %s", rvalue);
return 0;
}
if (m == KILL_NONE)
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Unit configured to use KillMode=none. "
"This is unsafe, as it disables systemd's process life-cycle management for the service. "
"Please update your service to use a safer KillMode=, such as 'mixed' or 'control-group'. "
"Support for KillMode=none is deprecated and will eventually be removed.");
*k = m;
return 0;
}
int config_parse_exec( int config_parse_exec(
const char *unit, const char *unit,
const char *filename, const char *filename,
@ -4823,7 +4782,7 @@ int unit_load_fragment(Unit *u) {
&u->manager->unit_name_map, &u->manager->unit_name_map,
&u->manager->unit_path_cache); &u->manager->unit_path_cache);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to rebuild name map: %m"); log_error_errno(r, "Failed to rebuild name map: %m");
r = unit_file_find_fragment(u->manager->unit_id_map, r = unit_file_find_fragment(u->manager->unit_id_map,
u->manager->unit_name_map, u->manager->unit_name_map,

View File

@ -517,7 +517,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
} else if (!value) { } else if (!value) {
const char *target; const char *target;
/* Compatible with SysV, but supported independently even if SysV compatiblity is disabled. */ /* SysV compatibility */
target = runlevel_to_target(key); target = runlevel_to_target(key);
if (target) if (target)
return free_and_strdup_warn(&arg_default_unit, target); return free_and_strdup_warn(&arg_default_unit, target);

View File

@ -679,12 +679,18 @@ static int manager_setup_prefix(Manager *m) {
[EXEC_DIRECTORY_CONFIGURATION] = { SD_PATH_USER_CONFIGURATION, NULL }, [EXEC_DIRECTORY_CONFIGURATION] = { SD_PATH_USER_CONFIGURATION, NULL },
}; };
assert(m); const struct table_entry *p;
ExecDirectoryType i;
const struct table_entry *p = MANAGER_IS_SYSTEM(m) ? paths_system : paths_user;
int r; int r;
for (ExecDirectoryType i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++) { assert(m);
if (MANAGER_IS_SYSTEM(m))
p = paths_system;
else
p = paths_user;
for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++) {
r = sd_path_lookup(p[i].type, p[i].suffix, &m->prefix[i]); r = sd_path_lookup(p[i].type, p[i].suffix, &m->prefix[i]);
if (r < 0) if (r < 0)
return r; return r;
@ -1338,12 +1344,15 @@ static void manager_clear_jobs_and_units(Manager *m) {
} }
Manager* manager_free(Manager *m) { Manager* manager_free(Manager *m) {
ExecDirectoryType dt;
UnitType c;
if (!m) if (!m)
return NULL; return NULL;
manager_clear_jobs_and_units(m); manager_clear_jobs_and_units(m);
for (UnitType c = 0; c < _UNIT_TYPE_MAX; c++) for (c = 0; c < _UNIT_TYPE_MAX; c++)
if (unit_vtable[c]->shutdown) if (unit_vtable[c]->shutdown)
unit_vtable[c]->shutdown(m); unit_vtable[c]->shutdown(m);
@ -1414,20 +1423,22 @@ Manager* manager_free(Manager *m) {
hashmap_free(m->uid_refs); hashmap_free(m->uid_refs);
hashmap_free(m->gid_refs); hashmap_free(m->gid_refs);
for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++) for (dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++)
m->prefix[dt] = mfree(m->prefix[dt]); m->prefix[dt] = mfree(m->prefix[dt]);
return mfree(m); return mfree(m);
} }
static void manager_enumerate_perpetual(Manager *m) { static void manager_enumerate_perpetual(Manager *m) {
UnitType c;
assert(m); assert(m);
if (m->test_run_flags == MANAGER_TEST_RUN_MINIMAL) if (m->test_run_flags == MANAGER_TEST_RUN_MINIMAL)
return; return;
/* Let's ask every type to load all units from disk/kernel that it might know */ /* Let's ask every type to load all units from disk/kernel that it might know */
for (UnitType c = 0; c < _UNIT_TYPE_MAX; c++) { for (c = 0; c < _UNIT_TYPE_MAX; c++) {
if (!unit_type_supported(c)) { if (!unit_type_supported(c)) {
log_debug("Unit type .%s is not supported on this system.", unit_type_to_string(c)); log_debug("Unit type .%s is not supported on this system.", unit_type_to_string(c));
continue; continue;
@ -1439,13 +1450,15 @@ static void manager_enumerate_perpetual(Manager *m) {
} }
static void manager_enumerate(Manager *m) { static void manager_enumerate(Manager *m) {
UnitType c;
assert(m); assert(m);
if (m->test_run_flags == MANAGER_TEST_RUN_MINIMAL) if (m->test_run_flags == MANAGER_TEST_RUN_MINIMAL)
return; return;
/* Let's ask every type to load all units from disk/kernel that it might know */ /* Let's ask every type to load all units from disk/kernel that it might know */
for (UnitType c = 0; c < _UNIT_TYPE_MAX; c++) { for (c = 0; c < _UNIT_TYPE_MAX; c++) {
if (!unit_type_supported(c)) { if (!unit_type_supported(c)) {
log_debug("Unit type .%s is not supported on this system.", unit_type_to_string(c)); log_debug("Unit type .%s is not supported on this system.", unit_type_to_string(c));
continue; continue;

View File

@ -863,8 +863,6 @@ static void mount_enter_dead(Mount *m, MountResult f) {
m->result = f; m->result = f;
unit_log_result(UNIT(m), m->result == MOUNT_SUCCESS, mount_result_to_string(m->result)); unit_log_result(UNIT(m), m->result == MOUNT_SUCCESS, mount_result_to_string(m->result));
unit_warn_leftover_processes(UNIT(m), unit_log_leftover_process_stop);
mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD); mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD);
m->exec_runtime = exec_runtime_unref(m->exec_runtime, true); m->exec_runtime = exec_runtime_unref(m->exec_runtime, true);
@ -1010,7 +1008,7 @@ static void mount_enter_mounting(Mount *m) {
(void) mkdir_p_label(m->where, m->directory_mode); (void) mkdir_p_label(m->where, m->directory_mode);
unit_warn_if_dir_nonempty(UNIT(m), m->where); unit_warn_if_dir_nonempty(UNIT(m), m->where);
unit_warn_leftover_processes(UNIT(m), unit_log_leftover_process_start); unit_warn_leftover_processes(UNIT(m));
m->control_command_id = MOUNT_EXEC_MOUNT; m->control_command_id = MOUNT_EXEC_MOUNT;
m->control_command = m->exec_command + MOUNT_EXEC_MOUNT; m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;

View File

@ -198,6 +198,15 @@ static void service_stop_watchdog(Service *s) {
s->watchdog_timestamp = DUAL_TIMESTAMP_NULL; s->watchdog_timestamp = DUAL_TIMESTAMP_NULL;
} }
static usec_t service_get_watchdog_usec(Service *s) {
assert(s);
if (s->watchdog_override_enable)
return s->watchdog_override_usec;
return s->watchdog_original_usec;
}
static void service_start_watchdog(Service *s) { static void service_start_watchdog(Service *s) {
usec_t watchdog_usec; usec_t watchdog_usec;
int r; int r;
@ -438,17 +447,14 @@ static int service_add_fd_store(Service *s, int fd, const char *name, bool do_po
} }
} }
fs = new(ServiceFDStore, 1); fs = new0(ServiceFDStore, 1);
if (!fs) if (!fs)
return -ENOMEM; return -ENOMEM;
*fs = (ServiceFDStore) { fs->fd = fd;
.fd = fd, fs->service = s;
.service = s, fs->do_poll = do_poll;
.do_poll = do_poll, fs->fdname = strdup(name ?: "stored");
.fdname = strdup(name ?: "stored"),
};
if (!fs->fdname) { if (!fs->fdname) {
free(fs); free(fs);
return -ENOMEM; return -ENOMEM;
@ -1749,7 +1755,6 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
unit_log_failure(UNIT(s), service_result_to_string(s->result)); unit_log_failure(UNIT(s), service_result_to_string(s->result));
end_state = SERVICE_FAILED; end_state = SERVICE_FAILED;
} }
unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_stop);
if (!allow_restart) if (!allow_restart)
log_unit_debug(UNIT(s), "Service restart not allowed."); log_unit_debug(UNIT(s), "Service restart not allowed.");
@ -2076,16 +2081,15 @@ static int service_adverse_to_leftover_processes(Service *s) {
assert(s); assert(s);
/* KillMode=mixed and control group are used to indicate that all process should be killed off. /* KillMode=mixed and control group are used to indicate that all process should be killed off.
* SendSIGKILL= is used for services that require a clean shutdown. These are typically database * SendSIGKILL is used for services that require a clean shutdown. These are typically database
* service where a SigKilled process would result in a lengthy recovery and who's shutdown or startup * service where a SigKilled process would result in a lengthy recovery and who's shutdown or
* time is quite variable (so Timeout settings aren't of use). * startup time is quite variable (so Timeout settings aren't of use).
* *
* Here we take these two factors and refuse to start a service if there are existing processes * Here we take these two factors and refuse to start a service if there are existing processes
* within a control group. Databases, while generally having some protection against multiple * within a control group. Databases, while generally having some protection against multiple
* instances running, lets not stress the rigor of these. Also ExecStartPre= parts of the service * instances running, lets not stress the rigor of these. Also ExecStartPre parts of the service
* aren't as rigoriously written to protect aganst against multiple use. */ * aren't as rigoriously written to protect aganst against multiple use. */
if (unit_warn_leftover_processes(UNIT(s)) &&
if (unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_start) > 0 &&
IN_SET(s->kill_context.kill_mode, KILL_MIXED, KILL_CONTROL_GROUP) && IN_SET(s->kill_context.kill_mode, KILL_MIXED, KILL_CONTROL_GROUP) &&
!s->kill_context.send_sigkill) !s->kill_context.send_sigkill)
return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(EBUSY), return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(EBUSY),

View File

@ -200,11 +200,6 @@ static inline usec_t service_timeout_abort_usec(Service *s) {
return s->timeout_abort_set ? s->timeout_abort_usec : s->timeout_stop_usec; return s->timeout_abort_set ? s->timeout_abort_usec : s->timeout_stop_usec;
} }
static inline usec_t service_get_watchdog_usec(Service *s) {
assert(s);
return s->watchdog_override_enable ? s->watchdog_override_usec : s->watchdog_original_usec;
}
extern const UnitVTable service_vtable; extern const UnitVTable service_vtable;
int service_set_socket_fd(Service *s, int fd, struct Socket *socket, bool selinux_context_net); int service_set_socket_fd(Service *s, int fd, struct Socket *socket, bool selinux_context_net);

View File

@ -2035,8 +2035,6 @@ static void socket_enter_dead(Socket *s, SocketResult f) {
else else
unit_log_failure(UNIT(s), socket_result_to_string(s->result)); unit_log_failure(UNIT(s), socket_result_to_string(s->result));
unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_stop);
socket_set_state(s, s->result != SOCKET_SUCCESS ? SOCKET_FAILED : SOCKET_DEAD); socket_set_state(s, s->result != SOCKET_SUCCESS ? SOCKET_FAILED : SOCKET_DEAD);
s->exec_runtime = exec_runtime_unref(s->exec_runtime, true); s->exec_runtime = exec_runtime_unref(s->exec_runtime, true);
@ -2239,7 +2237,7 @@ static void socket_enter_start_pre(Socket *s) {
socket_unwatch_control_pid(s); socket_unwatch_control_pid(s);
unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_start); unit_warn_leftover_processes(UNIT(s));
s->control_command_id = SOCKET_EXEC_START_PRE; s->control_command_id = SOCKET_EXEC_START_PRE;
s->control_command = s->exec_command[SOCKET_EXEC_START_PRE]; s->control_command = s->exec_command[SOCKET_EXEC_START_PRE];

View File

@ -701,7 +701,6 @@ static void swap_enter_dead(Swap *s, SwapResult f) {
s->result = f; s->result = f;
unit_log_result(UNIT(s), s->result == SWAP_SUCCESS, swap_result_to_string(s->result)); unit_log_result(UNIT(s), s->result == SWAP_SUCCESS, swap_result_to_string(s->result));
unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_stop);
swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD); swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD);
s->exec_runtime = exec_runtime_unref(s->exec_runtime, true); s->exec_runtime = exec_runtime_unref(s->exec_runtime, true);
@ -789,7 +788,7 @@ static void swap_enter_activating(Swap *s) {
assert(s); assert(s);
unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_start); unit_warn_leftover_processes(UNIT(s));
s->control_command_id = SWAP_EXEC_ACTIVATE; s->control_command_id = SWAP_EXEC_ACTIVATE;
s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE; s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE;

View File

@ -4971,11 +4971,11 @@ int unit_kill_context(
if (!pid_set) if (!pid_set)
return -ENOMEM; return -ENOMEM;
(void) cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
SIGHUP, SIGHUP,
CGROUP_IGNORE_SELF, CGROUP_IGNORE_SELF,
pid_set, pid_set,
NULL, NULL); NULL, NULL);
} }
} }
} }
@ -5861,20 +5861,14 @@ int unit_prepare_exec(Unit *u) {
return 0; return 0;
} }
static bool ignore_leftover_process(const char *comm) { static int log_leftover(pid_t pid, int sig, void *userdata) {
return comm && comm[0] == '('; /* Most likely our own helper process (PAM?), ignore */
}
int unit_log_leftover_process_start(pid_t pid, int sig, void *userdata) {
_cleanup_free_ char *comm = NULL; _cleanup_free_ char *comm = NULL;
(void) get_process_comm(pid, &comm); (void) get_process_comm(pid, &comm);
if (ignore_leftover_process(comm)) if (comm && comm[0] == '(') /* Most likely our own helper process (PAM?), ignore */
return 0; return 0;
/* During start we print a warning */
log_unit_warning(userdata, log_unit_warning(userdata,
"Found left-over process " PID_FMT " (%s) in control group while starting unit. Ignoring.\n" "Found left-over process " PID_FMT " (%s) in control group while starting unit. Ignoring.\n"
"This usually indicates unclean termination of a previous run, or service implementation deficiencies.", "This usually indicates unclean termination of a previous run, or service implementation deficiencies.",
@ -5883,24 +5877,7 @@ int unit_log_leftover_process_start(pid_t pid, int sig, void *userdata) {
return 1; return 1;
} }
int unit_log_leftover_process_stop(pid_t pid, int sig, void *userdata) { int unit_warn_leftover_processes(Unit *u) {
_cleanup_free_ char *comm = NULL;
(void) get_process_comm(pid, &comm);
if (ignore_leftover_process(comm))
return 0;
/* During stop we only print an informational message */
log_unit_info(userdata,
"Unit process " PID_FMT " (%s) remains running after unit stopped.",
pid, strna(comm));
return 1;
}
int unit_warn_leftover_processes(Unit *u, cg_kill_log_func_t log_func) {
assert(u); assert(u);
(void) unit_pick_cgroup_path(u); (void) unit_pick_cgroup_path(u);
@ -5908,7 +5885,7 @@ int unit_warn_leftover_processes(Unit *u, cg_kill_log_func_t log_func) {
if (!u->cgroup_path) if (!u->cgroup_path)
return 0; return 0;
return cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, 0, 0, NULL, log_func, u); return cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, 0, 0, NULL, log_leftover, u);
} }
bool unit_needs_console(Unit *u) { bool unit_needs_console(Unit *u) {

View File

@ -846,9 +846,7 @@ void unit_unlink_state_files(Unit *u);
int unit_prepare_exec(Unit *u); int unit_prepare_exec(Unit *u);
int unit_log_leftover_process_start(pid_t pid, int sig, void *userdata); int unit_warn_leftover_processes(Unit *u);
int unit_log_leftover_process_stop(pid_t pid, int sig, void *userdata);
int unit_warn_leftover_processes(Unit *u, cg_kill_log_func_t log_func);
bool unit_needs_console(Unit *u); bool unit_needs_console(Unit *u);

View File

@ -237,18 +237,18 @@ static int create_disk(
_cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = NULL, _cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = NULL,
*keydev_mount = NULL, *keyfile_timeout_value = NULL, *keydev_mount = NULL, *keyfile_timeout_value = NULL,
*filtered = NULL, *u_escaped = NULL, *name_escaped = NULL, *header_path = NULL, *password_buffer = NULL, *filtered = NULL, *u_escaped = NULL, *name_escaped = NULL, *header_path = NULL, *password_buffer = NULL;
*tmp_fstype = NULL;
_cleanup_fclose_ FILE *f = NULL; _cleanup_fclose_ FILE *f = NULL;
const char *dmname; const char *dmname;
bool noauto, nofail, swap, netdev, attach_in_initrd; bool noauto, nofail, tmp, swap, netdev, attach_in_initrd;
int r, detached_header, keyfile_can_timeout, tmp; int r, detached_header, keyfile_can_timeout;
assert(name); assert(name);
assert(device); assert(device);
noauto = fstab_test_yes_no_option(options, "noauto\0" "auto\0"); noauto = fstab_test_yes_no_option(options, "noauto\0" "auto\0");
nofail = fstab_test_yes_no_option(options, "nofail\0" "fail\0"); nofail = fstab_test_yes_no_option(options, "nofail\0" "fail\0");
tmp = fstab_test_option(options, "tmp\0");
swap = fstab_test_option(options, "swap\0"); swap = fstab_test_option(options, "swap\0");
netdev = fstab_test_option(options, "_netdev\0"); netdev = fstab_test_option(options, "_netdev\0");
attach_in_initrd = fstab_test_option(options, "x-initrd.attach\0"); attach_in_initrd = fstab_test_option(options, "x-initrd.attach\0");
@ -261,10 +261,6 @@ static int create_disk(
if (detached_header < 0) if (detached_header < 0)
return log_error_errno(detached_header, "Failed to parse header= option value: %m"); return log_error_errno(detached_header, "Failed to parse header= option value: %m");
tmp = fstab_filter_options(options, "tmp\0", NULL, &tmp_fstype, NULL);
if (tmp < 0)
return log_error_errno(tmp, "Failed to parse tmp= option value: %m");
if (tmp && swap) if (tmp && swap)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.", "Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.",
@ -375,19 +371,10 @@ static int create_disk(
if (r < 0) if (r < 0)
return r; return r;
if (tmp) { if (tmp)
_cleanup_free_ char *tmp_fstype_escaped = NULL;
if (tmp_fstype) {
tmp_fstype_escaped = specifier_escape(tmp_fstype);
if (!tmp_fstype_escaped)
return log_oom();
}
fprintf(f, fprintf(f,
"ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs '%s' '/dev/mapper/%s'\n", "ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs ext2 '/dev/mapper/%s'\n",
tmp_fstype_escaped ?: "ext4", name_escaped); name_escaped);
}
if (swap) if (swap)
fprintf(f, fprintf(f,

View File

@ -78,6 +78,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_uri, freep);
loud loud
quiet quiet
keyscript= keyscript=
tmp= (the version without argument is supported)
initramfs initramfs
*/ */
@ -231,8 +232,7 @@ static int parse_one_option(const char *option) {
} else if (STR_IN_SET(option, "tcrypt-veracrypt", "veracrypt")) { } else if (STR_IN_SET(option, "tcrypt-veracrypt", "veracrypt")) {
arg_type = CRYPT_TCRYPT; arg_type = CRYPT_TCRYPT;
arg_tcrypt_veracrypt = true; arg_tcrypt_veracrypt = true;
} else if (STR_IN_SET(option, "plain", "swap", "tmp") || } else if (STR_IN_SET(option, "plain", "swap", "tmp"))
startswith(option, "tmp="))
arg_type = CRYPT_PLAIN; arg_type = CRYPT_PLAIN;
else if ((val = startswith(option, "timeout="))) { else if ((val = startswith(option, "timeout="))) {

View File

@ -978,11 +978,8 @@ typedef struct RunContext {
PTYForward *forward; PTYForward *forward;
sd_bus_slot *match; sd_bus_slot *match;
/* Current state of the unit */
char *active_state;
bool has_job;
/* The exit data of the unit */ /* The exit data of the unit */
char *active_state;
uint64_t inactive_exit_usec; uint64_t inactive_exit_usec;
uint64_t inactive_enter_usec; uint64_t inactive_enter_usec;
char *result; char *result;
@ -1013,7 +1010,7 @@ static void run_context_check_done(RunContext *c) {
assert(c); assert(c);
if (c->match) if (c->match)
done = STRPTR_IN_SET(c->active_state, "inactive", "failed") && !c->has_job; done = STRPTR_IN_SET(c->active_state, "inactive", "failed");
else else
done = true; done = true;
@ -1024,35 +1021,20 @@ static void run_context_check_done(RunContext *c) {
sd_event_exit(c->event, EXIT_SUCCESS); sd_event_exit(c->event, EXIT_SUCCESS);
} }
static int map_job(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
bool *b = userdata;
const char *job;
uint32_t id;
int r;
r = sd_bus_message_read(m, "(uo)", &id, &job);
if (r < 0)
return r;
*b = id != 0 || !streq(job, "/");
return 0;
}
static int run_context_update(RunContext *c, const char *path) { static int run_context_update(RunContext *c, const char *path) {
static const struct bus_properties_map map[] = { static const struct bus_properties_map map[] = {
{ "ActiveState", "s", NULL, offsetof(RunContext, active_state) }, { "ActiveState", "s", NULL, offsetof(RunContext, active_state) },
{ "InactiveExitTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_exit_usec) }, { "InactiveExitTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_exit_usec) },
{ "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_enter_usec) }, { "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_enter_usec) },
{ "Result", "s", NULL, offsetof(RunContext, result) }, { "Result", "s", NULL, offsetof(RunContext, result) },
{ "ExecMainCode", "i", NULL, offsetof(RunContext, exit_code) }, { "ExecMainCode", "i", NULL, offsetof(RunContext, exit_code) },
{ "ExecMainStatus", "i", NULL, offsetof(RunContext, exit_status) }, { "ExecMainStatus", "i", NULL, offsetof(RunContext, exit_status) },
{ "CPUUsageNSec", "t", NULL, offsetof(RunContext, cpu_usage_nsec) }, { "CPUUsageNSec", "t", NULL, offsetof(RunContext, cpu_usage_nsec) },
{ "IPIngressBytes", "t", NULL, offsetof(RunContext, ip_ingress_bytes) }, { "IPIngressBytes", "t", NULL, offsetof(RunContext, ip_ingress_bytes) },
{ "IPEgressBytes", "t", NULL, offsetof(RunContext, ip_egress_bytes) }, { "IPEgressBytes", "t", NULL, offsetof(RunContext, ip_egress_bytes) },
{ "IOReadBytes", "t", NULL, offsetof(RunContext, io_read_bytes) }, { "IOReadBytes", "t", NULL, offsetof(RunContext, io_read_bytes) },
{ "IOWriteBytes", "t", NULL, offsetof(RunContext, io_write_bytes) }, { "IOWriteBytes", "t", NULL, offsetof(RunContext, io_write_bytes) },
{ "Job", "(uo)", map_job, offsetof(RunContext, has_job) },
{} {}
}; };

View File

@ -531,11 +531,15 @@ int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) {
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to read LoaderTimeExecUSec: %m"); return log_debug_errno(r, "Failed to read LoaderTimeExecUSec: %m");
if (y == 0 || y < x || y - x > USEC_PER_HOUR) if (y == 0 || y < x)
return log_debug_errno(SYNTHETIC_ERRNO(EIO), return log_debug_errno(SYNTHETIC_ERRNO(EIO),
"Bad LoaderTimeInitUSec=%"PRIu64", LoaderTimeExecUSec=%" PRIu64"; refusing.", "Bad LoaderTimeInitUSec=%"PRIu64", LoaderTimeExecUSec=%" PRIu64"; refusing.",
x, y); x, y);
if (y > USEC_PER_HOUR)
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
"LoaderTimeExecUSec=%"PRIu64" too large, refusing.", x);
*firmware = x; *firmware = x;
*loader = y; *loader = y;

View File

@ -80,7 +80,7 @@ int fstab_is_mount_point(const char *mount) {
} }
int fstab_filter_options(const char *opts, const char *names, int fstab_filter_options(const char *opts, const char *names,
const char **ret_namefound, char **ret_value, char **ret_filtered) { const char **namefound, char **value, char **filtered) {
const char *name, *n = NULL, *x; const char *name, *n = NULL, *x;
_cleanup_strv_free_ char **stor = NULL; _cleanup_strv_free_ char **stor = NULL;
_cleanup_free_ char *v = NULL, **strv = NULL; _cleanup_free_ char *v = NULL, **strv = NULL;
@ -92,7 +92,7 @@ int fstab_filter_options(const char *opts, const char *names,
/* If !value and !filtered, this function is not allowed to fail. */ /* If !value and !filtered, this function is not allowed to fail. */
if (!ret_filtered) { if (!filtered) {
const char *word, *state; const char *word, *state;
size_t l; size_t l;
@ -108,7 +108,7 @@ int fstab_filter_options(const char *opts, const char *names,
x = word + strlen(name); x = word + strlen(name);
if (IN_SET(*x, '\0', '=', ',')) { if (IN_SET(*x, '\0', '=', ',')) {
n = name; n = name;
if (ret_value) { if (value) {
free(v); free(v);
if (IN_SET(*x, '\0', ',')) if (IN_SET(*x, '\0', ','))
v = NULL; v = NULL;
@ -145,7 +145,7 @@ int fstab_filter_options(const char *opts, const char *names,
found: found:
/* Keep the last occurrence found */ /* Keep the last occurrence found */
n = name; n = name;
if (ret_value) { if (value) {
free(v); free(v);
if (*x == '\0') if (*x == '\0')
v = NULL; v = NULL;
@ -162,19 +162,19 @@ int fstab_filter_options(const char *opts, const char *names,
} }
answer: answer:
if (ret_namefound) if (namefound)
*ret_namefound = n; *namefound = n;
if (ret_filtered) { if (filtered) {
char *f; char *f;
f = strv_join(strv, ","); f = strv_join(strv, ",");
if (!f) if (!f)
return -ENOMEM; return -ENOMEM;
*ret_filtered = f; *filtered = f;
} }
if (ret_value) if (value)
*ret_value = TAKE_PTR(v); *value = TAKE_PTR(v);
return !!n; return !!n;
} }

View File

@ -788,25 +788,19 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
if (!fpath) if (!fpath)
return log_oom(); return log_oom();
log_warning("SysV service '%s' lacks a native systemd unit file. " service = new0(SysvStub, 1);
"Automatically generating a unit file for compatibility. "
"Please update package to include a native systemd unit file, in order to make it more safe and robust.", fpath);
service = new(SysvStub, 1);
if (!service) if (!service)
return log_oom(); return log_oom();
*service = (SysvStub) { service->sysv_start_priority = -1;
.sysv_start_priority = -1, service->name = TAKE_PTR(name);
.name = TAKE_PTR(name), service->path = TAKE_PTR(fpath);
.path = TAKE_PTR(fpath),
};
r = hashmap_put(all_services, service->name, service); r = hashmap_put(all_services, service->name, service);
if (r < 0) if (r < 0)
return log_oom(); return log_oom();
TAKE_PTR(service); service = NULL;
} }
} }

View File

@ -724,7 +724,7 @@ static int run(int argc, char *argv[]) {
last_busy_usec = n; last_busy_usec = n;
else if (listen_idle_usec != USEC_INFINITY && n >= usec_add(last_busy_usec, listen_idle_usec)) { else if (listen_idle_usec != USEC_INFINITY && n >= usec_add(last_busy_usec, listen_idle_usec)) {
char buf[FORMAT_TIMESPAN_MAX]; char buf[FORMAT_TIMESPAN_MAX];
log_debug("Exiting worker, been idle for %s.", log_debug("Exiting worker, been idle for %s, .",
format_timespan(buf, sizeof(buf), usec_sub_unsigned(n, last_busy_usec), 0)); format_timespan(buf, sizeof(buf), usec_sub_unsigned(n, last_busy_usec), 0));
break; break;
} }

View File

@ -1,13 +1,5 @@
# SPDX-License-Identifier: LGPL-2.1+ # SPDX-License-Identifier: LGPL-2.1+
# The 'optimization' option was introduced in meson 0.48.0, so let's keep
# the code compatible with older versions as well
if meson.version().version_compare('>=0.48.0')
optimization = '--optimization=@0@'.format(get_option('optimization'))
else
optimization = ''
endif
sanitize_address_undefined = custom_target( sanitize_address_undefined = custom_target(
'sanitize-address-undefined-fuzzers', 'sanitize-address-undefined-fuzzers',
output : 'sanitize-address-undefined-fuzzers', output : 'sanitize-address-undefined-fuzzers',
@ -15,7 +7,8 @@ sanitize_address_undefined = custom_target(
project_source_root, project_source_root,
'@OUTPUT@', '@OUTPUT@',
'fuzzers', 'fuzzers',
'-Db_lundef=false -Db_sanitize=address,undefined @0@'.format(optimization), '-Db_lundef=false -Db_sanitize=address,undefined ' +
'--optimization=@0@'.format(get_option('optimization')),
' '.join(cc.cmd_array()), ' '.join(cc.cmd_array()),
cxx_cmd]) cxx_cmd])

View File

@ -678,7 +678,6 @@ cleanup_loopdev() {
if [ -n "${LOOPDEV}" ]; then if [ -n "${LOOPDEV}" ]; then
ddebug "losetup -d $LOOPDEV" ddebug "losetup -d $LOOPDEV"
losetup -d "${LOOPDEV}" losetup -d "${LOOPDEV}"
unset LOOPDEV
fi fi
} }
@ -699,7 +698,8 @@ create_empty_image() {
rm -f "$IMAGE_PRIVATE" "$IMAGE_PUBLIC" rm -f "$IMAGE_PRIVATE" "$IMAGE_PUBLIC"
# Create the blank file to use as a root filesystem # Create the blank file to use as a root filesystem
truncate -s "${_size}M" "$IMAGE_PUBLIC" truncate -s "${_size}M" "$IMAGE_PRIVATE"
ln -vs "$(realpath $IMAGE_PRIVATE)" "$IMAGE_PUBLIC"
LOOPDEV=$(losetup --show -P -f "$IMAGE_PUBLIC") LOOPDEV=$(losetup --show -P -f "$IMAGE_PUBLIC")
[ -b "$LOOPDEV" ] || return 1 [ -b "$LOOPDEV" ] || return 1
@ -2005,26 +2005,16 @@ test_setup() {
if [ -e "$IMAGE_PRIVATE" ]; then if [ -e "$IMAGE_PRIVATE" ]; then
echo "Reusing existing image $IMAGE_PRIVATE → $(realpath $IMAGE_PRIVATE)" echo "Reusing existing image $IMAGE_PRIVATE → $(realpath $IMAGE_PRIVATE)"
mount_initdir mount_initdir
else elif [ -e "$IMAGE_PUBLIC" ]; then
if [ ! -e "$IMAGE_PUBLIC" ]; then
# Create the backing public image, but then completely unmount
# it and drop the loopback device responsible for it, since we're
# going to symlink/copy the image and mount it again from
# elsewhere.
test_create_image
test_setup_cleanup
umount_loopback
cleanup_loopdev
fi
echo "Reusing existing cached image $IMAGE_PUBLIC → $(realpath $IMAGE_PUBLIC)" echo "Reusing existing cached image $IMAGE_PUBLIC → $(realpath $IMAGE_PUBLIC)"
if [ ${TEST_PARALLELIZE} -ne 0 ]; then if [ ${TEST_PARALLELIZE} -ne 0 ]; then
cp -v "$(realpath $IMAGE_PUBLIC)" "$IMAGE_PRIVATE" cp -v "$(realpath $IMAGE_PUBLIC)" "$IMAGE_PRIVATE"
else else
ln -sv "$(realpath $IMAGE_PUBLIC)" "$IMAGE_PRIVATE" ln -sv "$(realpath $IMAGE_PUBLIC)" "$IMAGE_PRIVATE"
fi fi
mount_initdir mount_initdir
else
test_create_image
fi fi
setup_nspawn_root setup_nspawn_root

View File

@ -30,9 +30,7 @@ UtmpIdentifier=cons
TTYPath=/dev/console TTYPath=/dev/console
TTYReset=yes TTYReset=yes
TTYVHangup=yes TTYVHangup=yes
m4_ifdef(`ENABLE_LOGIND',,
KillMode=process KillMode=process
)m4_dnl
IgnoreSIGPIPE=no IgnoreSIGPIPE=no
SendSIGHUP=yes SendSIGHUP=yes

View File

@ -36,8 +36,6 @@ UtmpIdentifier=pts/%I
TTYPath=/dev/pts/%I TTYPath=/dev/pts/%I
TTYReset=yes TTYReset=yes
TTYVHangup=yes TTYVHangup=yes
m4_ifdef(`ENABLE_LOGIND',,
KillMode=process KillMode=process
)m4_dnl
IgnoreSIGPIPE=no IgnoreSIGPIPE=no
SendSIGHUP=yes SendSIGHUP=yes

View File

@ -47,9 +47,7 @@ TTYPath=/dev/%I
TTYReset=yes TTYReset=yes
TTYVHangup=yes TTYVHangup=yes
TTYVTDisallocate=yes TTYVTDisallocate=yes
m4_ifdef(`ENABLE_LOGIND',,
KillMode=process KillMode=process
)m4_dnl
IgnoreSIGPIPE=no IgnoreSIGPIPE=no
SendSIGHUP=yes SendSIGHUP=yes

View File

@ -40,9 +40,7 @@ UtmpIdentifier=%I
TTYPath=/dev/%I TTYPath=/dev/%I
TTYReset=yes TTYReset=yes
TTYVHangup=yes TTYVHangup=yes
m4_ifdef(`ENABLE_LOGIND',,
KillMode=process KillMode=process
)m4_dnl
IgnoreSIGPIPE=no IgnoreSIGPIPE=no
SendSIGHUP=yes SendSIGHUP=yes