Compare commits
24 Commits
9554b8d1d1
...
49d5aae503
Author | SHA1 | Date |
---|---|---|
Lennart Poettering | 49d5aae503 | |
Lennart Poettering | 6d02412d51 | |
Chris Kerr | 8aa36b1ddd | |
Lennart Poettering | 2b5f708985 | |
Lennart Poettering | 518a9bd689 | |
Frantisek Sumsal | ffbb0fb9cb | |
Chris Down | 4793c31083 | |
Zbigniew Jędrzejewski-Szmek | dde5c821bf | |
Zbigniew Jędrzejewski-Szmek | 24b4597064 | |
Zbigniew Jędrzejewski-Szmek | 40fd0a77c6 | |
Zbigniew Jędrzejewski-Szmek | 1414090854 | |
Zbigniew Jędrzejewski-Szmek | 3035a7c577 | |
Frantisek Sumsal | 2991fa41e4 | |
Lennart Poettering | effefa30de | |
Lennart Poettering | 0e42cbe254 | |
Lennart Poettering | 470ab28d07 | |
Lennart Poettering | c8aa4b5b86 | |
Lennart Poettering | b0cea477d4 | |
Lennart Poettering | 4c42543429 | |
Lennart Poettering | 021acbc188 | |
Lennart Poettering | 9b52e0d81a | |
Lennart Poettering | d068765b68 | |
Lennart Poettering | 53ac130b51 | |
Lennart Poettering | 92a08691c2 |
2
TODO
2
TODO
|
@ -19,6 +19,8 @@ Janitorial Clean-ups:
|
|||
|
||||
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
|
||||
pages, and include hyperlinks to them in the journal output
|
||||
|
||||
|
|
|
@ -393,18 +393,17 @@
|
|||
</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 <filename>/tmp</filename>; it will be
|
||||
formatted using
|
||||
<citerefentry project='man-pages'><refentrytitle>mke2fs</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
|
||||
This option implies <option>plain</option>.</para>
|
||||
<listitem><para>The encrypted block device will be prepared for using it as
|
||||
<filename>/tmp/</filename>; it will be formatted using <citerefentry
|
||||
project='man-pages'><refentrytitle>mkfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>. Takes
|
||||
a file system type as argument, such as <literal>ext4</literal>, <literal>xfs</literal> or
|
||||
<literal>btrfs</literal>. If no argument is specified defaults to <literal>ext4</literal>. This
|
||||
option implies <option>plain</option>.</para>
|
||||
|
||||
<para>WARNING: Using the <option>tmp</option> option will
|
||||
destroy the contents of the named partition during every boot,
|
||||
so make sure the underlying block device is specified
|
||||
correctly.</para></listitem>
|
||||
<para>WARNING: Using the <option>tmp</option> option will destroy the contents of the named partition
|
||||
during every boot, so make sure the underlying block device is specified correctly.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
|
|
@ -61,28 +61,25 @@
|
|||
|
||||
<varlistentry>
|
||||
<term><varname>KillMode=</varname></term>
|
||||
<listitem><para>Specifies how processes of this unit shall be
|
||||
killed. One of
|
||||
<option>control-group</option>,
|
||||
<option>process</option>,
|
||||
<option>mixed</option>,
|
||||
<listitem><para>Specifies how processes of this unit shall be killed. One of
|
||||
<option>control-group</option>, <option>mixed</option>, <option>process</option>,
|
||||
<option>none</option>.</para>
|
||||
|
||||
<para>If set to <option>control-group</option>, all remaining
|
||||
processes in the control group of this unit will be killed on
|
||||
unit stop (for services: after the stop command is executed,
|
||||
as configured with <varname>ExecStop=</varname>). If set to
|
||||
<option>process</option>, only the main process itself is
|
||||
killed. If set to <option>mixed</option>, the
|
||||
<constant>SIGTERM</constant> signal (see below) is sent to the
|
||||
main process while the subsequent <constant>SIGKILL</constant>
|
||||
signal (see below) is sent to all remaining processes of the
|
||||
unit's control group. If set to <option>none</option>, no
|
||||
process is killed. In this case, only the stop command will be
|
||||
executed on unit stop, but no process will be killed otherwise.
|
||||
Processes remaining alive after stop are left in their control
|
||||
group and the control group continues to exist after stop
|
||||
unless it is empty.</para>
|
||||
<para>If set to <option>control-group</option>, all remaining processes in the control group of this
|
||||
unit will be killed on unit stop (for services: after the stop command is executed, as configured
|
||||
with <varname>ExecStop=</varname>). If set to <option>mixed</option>, the
|
||||
<constant>SIGTERM</constant> signal (see below) is sent to the main process while the subsequent
|
||||
<constant>SIGKILL</constant> signal (see below) is sent to all remaining processes of the unit's
|
||||
control group. If set to <option>process</option>, only the main process itself is killed (not
|
||||
recommended!). If set to <option>none</option>, no process is killed (strongly recommended
|
||||
against!). In this case, only the stop command will be executed on unit stop, but no process will be
|
||||
killed otherwise. Processes remaining alive after stop are left in their control group and the
|
||||
control group continues to exist after stop unless empty.</para>
|
||||
|
||||
<para>Note that it is not recommended to set <varname>KillMode=</varname> to
|
||||
<constant>process</constant> or even <constant>none</constant>, as this allows processes to escape
|
||||
the service manager's lifecycle and resource management, and to remain running even while their
|
||||
service is considered stopped and is assumed to not consume any resources.</para>
|
||||
|
||||
<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,
|
||||
|
|
|
@ -1550,7 +1550,7 @@
|
|||
already existing public-key cryptography, for post-quantum
|
||||
resistance.
|
||||
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-networkd</literal>
|
||||
the permissions of the .netdev file to be owned by <literal>root:systemd-network</literal>
|
||||
with a <literal>0640</literal> file mode.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
|
|
@ -28,6 +28,7 @@ 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_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_watchdog_usec, "t", Service, service_get_watchdog_usec);
|
||||
|
||||
static int property_get_exit_status_set(
|
||||
sd_bus *bus,
|
||||
|
@ -101,7 +102,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("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("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("WatchdogUSec", "t", property_get_watchdog_usec, 0, 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("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
|
|
@ -117,7 +117,6 @@ 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_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_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_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");
|
||||
|
@ -631,6 +630,48 @@ int config_parse_exec_coredump_filter(
|
|||
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(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
|
@ -4782,7 +4823,7 @@ int unit_load_fragment(Unit *u) {
|
|||
&u->manager->unit_name_map,
|
||||
&u->manager->unit_path_cache);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed to rebuild name map: %m");
|
||||
return log_error_errno(r, "Failed to rebuild name map: %m");
|
||||
|
||||
r = unit_file_find_fragment(u->manager->unit_id_map,
|
||||
u->manager->unit_name_map,
|
||||
|
|
|
@ -517,7 +517,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||
} else if (!value) {
|
||||
const char *target;
|
||||
|
||||
/* SysV compatibility */
|
||||
/* Compatible with SysV, but supported independently even if SysV compatiblity is disabled. */
|
||||
target = runlevel_to_target(key);
|
||||
if (target)
|
||||
return free_and_strdup_warn(&arg_default_unit, target);
|
||||
|
|
|
@ -679,18 +679,12 @@ static int manager_setup_prefix(Manager *m) {
|
|||
[EXEC_DIRECTORY_CONFIGURATION] = { SD_PATH_USER_CONFIGURATION, NULL },
|
||||
};
|
||||
|
||||
const struct table_entry *p;
|
||||
ExecDirectoryType i;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (MANAGER_IS_SYSTEM(m))
|
||||
p = paths_system;
|
||||
else
|
||||
p = paths_user;
|
||||
const struct table_entry *p = MANAGER_IS_SYSTEM(m) ? paths_system : paths_user;
|
||||
int r;
|
||||
|
||||
for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++) {
|
||||
for (ExecDirectoryType i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++) {
|
||||
r = sd_path_lookup(p[i].type, p[i].suffix, &m->prefix[i]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -1344,15 +1338,12 @@ static void manager_clear_jobs_and_units(Manager *m) {
|
|||
}
|
||||
|
||||
Manager* manager_free(Manager *m) {
|
||||
ExecDirectoryType dt;
|
||||
UnitType c;
|
||||
|
||||
if (!m)
|
||||
return NULL;
|
||||
|
||||
manager_clear_jobs_and_units(m);
|
||||
|
||||
for (c = 0; c < _UNIT_TYPE_MAX; c++)
|
||||
for (UnitType c = 0; c < _UNIT_TYPE_MAX; c++)
|
||||
if (unit_vtable[c]->shutdown)
|
||||
unit_vtable[c]->shutdown(m);
|
||||
|
||||
|
@ -1423,22 +1414,20 @@ Manager* manager_free(Manager *m) {
|
|||
hashmap_free(m->uid_refs);
|
||||
hashmap_free(m->gid_refs);
|
||||
|
||||
for (dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++)
|
||||
for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++)
|
||||
m->prefix[dt] = mfree(m->prefix[dt]);
|
||||
|
||||
return mfree(m);
|
||||
}
|
||||
|
||||
static void manager_enumerate_perpetual(Manager *m) {
|
||||
UnitType c;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (m->test_run_flags == MANAGER_TEST_RUN_MINIMAL)
|
||||
return;
|
||||
|
||||
/* Let's ask every type to load all units from disk/kernel that it might know */
|
||||
for (c = 0; c < _UNIT_TYPE_MAX; c++) {
|
||||
for (UnitType c = 0; c < _UNIT_TYPE_MAX; c++) {
|
||||
if (!unit_type_supported(c)) {
|
||||
log_debug("Unit type .%s is not supported on this system.", unit_type_to_string(c));
|
||||
continue;
|
||||
|
@ -1450,15 +1439,13 @@ static void manager_enumerate_perpetual(Manager *m) {
|
|||
}
|
||||
|
||||
static void manager_enumerate(Manager *m) {
|
||||
UnitType c;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (m->test_run_flags == MANAGER_TEST_RUN_MINIMAL)
|
||||
return;
|
||||
|
||||
/* Let's ask every type to load all units from disk/kernel that it might know */
|
||||
for (c = 0; c < _UNIT_TYPE_MAX; c++) {
|
||||
for (UnitType c = 0; c < _UNIT_TYPE_MAX; c++) {
|
||||
if (!unit_type_supported(c)) {
|
||||
log_debug("Unit type .%s is not supported on this system.", unit_type_to_string(c));
|
||||
continue;
|
||||
|
|
|
@ -863,6 +863,8 @@ static void mount_enter_dead(Mount *m, MountResult f) {
|
|||
m->result = f;
|
||||
|
||||
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);
|
||||
|
||||
m->exec_runtime = exec_runtime_unref(m->exec_runtime, true);
|
||||
|
@ -1008,7 +1010,7 @@ static void mount_enter_mounting(Mount *m) {
|
|||
(void) mkdir_p_label(m->where, m->directory_mode);
|
||||
|
||||
unit_warn_if_dir_nonempty(UNIT(m), m->where);
|
||||
unit_warn_leftover_processes(UNIT(m));
|
||||
unit_warn_leftover_processes(UNIT(m), unit_log_leftover_process_start);
|
||||
|
||||
m->control_command_id = MOUNT_EXEC_MOUNT;
|
||||
m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;
|
||||
|
|
|
@ -198,15 +198,6 @@ static void service_stop_watchdog(Service *s) {
|
|||
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) {
|
||||
usec_t watchdog_usec;
|
||||
int r;
|
||||
|
@ -447,14 +438,17 @@ static int service_add_fd_store(Service *s, int fd, const char *name, bool do_po
|
|||
}
|
||||
}
|
||||
|
||||
fs = new0(ServiceFDStore, 1);
|
||||
fs = new(ServiceFDStore, 1);
|
||||
if (!fs)
|
||||
return -ENOMEM;
|
||||
|
||||
fs->fd = fd;
|
||||
fs->service = s;
|
||||
fs->do_poll = do_poll;
|
||||
fs->fdname = strdup(name ?: "stored");
|
||||
*fs = (ServiceFDStore) {
|
||||
.fd = fd,
|
||||
.service = s,
|
||||
.do_poll = do_poll,
|
||||
.fdname = strdup(name ?: "stored"),
|
||||
};
|
||||
|
||||
if (!fs->fdname) {
|
||||
free(fs);
|
||||
return -ENOMEM;
|
||||
|
@ -1755,6 +1749,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
|
|||
unit_log_failure(UNIT(s), service_result_to_string(s->result));
|
||||
end_state = SERVICE_FAILED;
|
||||
}
|
||||
unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_stop);
|
||||
|
||||
if (!allow_restart)
|
||||
log_unit_debug(UNIT(s), "Service restart not allowed.");
|
||||
|
@ -2081,15 +2076,16 @@ static int service_adverse_to_leftover_processes(Service *s) {
|
|||
assert(s);
|
||||
|
||||
/* 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
|
||||
* service where a SigKilled process would result in a lengthy recovery and who's shutdown or
|
||||
* startup time is quite variable (so Timeout settings aren't of use).
|
||||
* 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
|
||||
* 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
|
||||
* 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. */
|
||||
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) &&
|
||||
!s->kill_context.send_sigkill)
|
||||
return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(EBUSY),
|
||||
|
|
|
@ -200,6 +200,11 @@ static inline usec_t service_timeout_abort_usec(Service *s) {
|
|||
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;
|
||||
|
||||
int service_set_socket_fd(Service *s, int fd, struct Socket *socket, bool selinux_context_net);
|
||||
|
|
|
@ -2035,6 +2035,8 @@ static void socket_enter_dead(Socket *s, SocketResult f) {
|
|||
else
|
||||
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);
|
||||
|
||||
s->exec_runtime = exec_runtime_unref(s->exec_runtime, true);
|
||||
|
@ -2237,7 +2239,7 @@ static void socket_enter_start_pre(Socket *s) {
|
|||
|
||||
socket_unwatch_control_pid(s);
|
||||
|
||||
unit_warn_leftover_processes(UNIT(s));
|
||||
unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_start);
|
||||
|
||||
s->control_command_id = SOCKET_EXEC_START_PRE;
|
||||
s->control_command = s->exec_command[SOCKET_EXEC_START_PRE];
|
||||
|
|
|
@ -701,6 +701,7 @@ static void swap_enter_dead(Swap *s, SwapResult f) {
|
|||
s->result = f;
|
||||
|
||||
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);
|
||||
|
||||
s->exec_runtime = exec_runtime_unref(s->exec_runtime, true);
|
||||
|
@ -788,7 +789,7 @@ static void swap_enter_activating(Swap *s) {
|
|||
|
||||
assert(s);
|
||||
|
||||
unit_warn_leftover_processes(UNIT(s));
|
||||
unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_start);
|
||||
|
||||
s->control_command_id = SWAP_EXEC_ACTIVATE;
|
||||
s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE;
|
||||
|
|
|
@ -4971,11 +4971,11 @@ int unit_kill_context(
|
|||
if (!pid_set)
|
||||
return -ENOMEM;
|
||||
|
||||
cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
|
||||
SIGHUP,
|
||||
CGROUP_IGNORE_SELF,
|
||||
pid_set,
|
||||
NULL, NULL);
|
||||
(void) cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
|
||||
SIGHUP,
|
||||
CGROUP_IGNORE_SELF,
|
||||
pid_set,
|
||||
NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5861,14 +5861,20 @@ int unit_prepare_exec(Unit *u) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int log_leftover(pid_t pid, int sig, void *userdata) {
|
||||
static bool ignore_leftover_process(const char *comm) {
|
||||
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;
|
||||
|
||||
(void) get_process_comm(pid, &comm);
|
||||
|
||||
if (comm && comm[0] == '(') /* Most likely our own helper process (PAM?), ignore */
|
||||
if (ignore_leftover_process(comm))
|
||||
return 0;
|
||||
|
||||
/* During start we print a warning */
|
||||
|
||||
log_unit_warning(userdata,
|
||||
"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.",
|
||||
|
@ -5877,7 +5883,24 @@ static int log_leftover(pid_t pid, int sig, void *userdata) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int unit_warn_leftover_processes(Unit *u) {
|
||||
int unit_log_leftover_process_stop(pid_t pid, int sig, void *userdata) {
|
||||
_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);
|
||||
|
||||
(void) unit_pick_cgroup_path(u);
|
||||
|
@ -5885,7 +5908,7 @@ int unit_warn_leftover_processes(Unit *u) {
|
|||
if (!u->cgroup_path)
|
||||
return 0;
|
||||
|
||||
return cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, 0, 0, NULL, log_leftover, u);
|
||||
return cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, 0, 0, NULL, log_func, u);
|
||||
}
|
||||
|
||||
bool unit_needs_console(Unit *u) {
|
||||
|
|
|
@ -846,7 +846,9 @@ void unit_unlink_state_files(Unit *u);
|
|||
|
||||
int unit_prepare_exec(Unit *u);
|
||||
|
||||
int unit_warn_leftover_processes(Unit *u);
|
||||
int unit_log_leftover_process_start(pid_t pid, int sig, void *userdata);
|
||||
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);
|
||||
|
||||
|
|
|
@ -237,18 +237,18 @@ static int create_disk(
|
|||
|
||||
_cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = 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;
|
||||
const char *dmname;
|
||||
bool noauto, nofail, tmp, swap, netdev, attach_in_initrd;
|
||||
int r, detached_header, keyfile_can_timeout;
|
||||
bool noauto, nofail, swap, netdev, attach_in_initrd;
|
||||
int r, detached_header, keyfile_can_timeout, tmp;
|
||||
|
||||
assert(name);
|
||||
assert(device);
|
||||
|
||||
noauto = fstab_test_yes_no_option(options, "noauto\0" "auto\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");
|
||||
netdev = fstab_test_option(options, "_netdev\0");
|
||||
attach_in_initrd = fstab_test_option(options, "x-initrd.attach\0");
|
||||
|
@ -261,6 +261,10 @@ static int create_disk(
|
|||
if (detached_header < 0)
|
||||
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)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.",
|
||||
|
@ -371,10 +375,19 @@ static int create_disk(
|
|||
if (r < 0)
|
||||
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,
|
||||
"ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs ext2 '/dev/mapper/%s'\n",
|
||||
name_escaped);
|
||||
"ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs '%s' '/dev/mapper/%s'\n",
|
||||
tmp_fstype_escaped ?: "ext4", name_escaped);
|
||||
}
|
||||
|
||||
if (swap)
|
||||
fprintf(f,
|
||||
|
|
|
@ -78,7 +78,6 @@ STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_uri, freep);
|
|||
loud
|
||||
quiet
|
||||
keyscript=
|
||||
tmp= (the version without argument is supported)
|
||||
initramfs
|
||||
*/
|
||||
|
||||
|
@ -232,7 +231,8 @@ static int parse_one_option(const char *option) {
|
|||
} else if (STR_IN_SET(option, "tcrypt-veracrypt", "veracrypt")) {
|
||||
arg_type = CRYPT_TCRYPT;
|
||||
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;
|
||||
else if ((val = startswith(option, "timeout="))) {
|
||||
|
||||
|
|
|
@ -978,8 +978,11 @@ typedef struct RunContext {
|
|||
PTYForward *forward;
|
||||
sd_bus_slot *match;
|
||||
|
||||
/* The exit data of the unit */
|
||||
/* Current state of the unit */
|
||||
char *active_state;
|
||||
bool has_job;
|
||||
|
||||
/* The exit data of the unit */
|
||||
uint64_t inactive_exit_usec;
|
||||
uint64_t inactive_enter_usec;
|
||||
char *result;
|
||||
|
@ -1010,7 +1013,7 @@ static void run_context_check_done(RunContext *c) {
|
|||
assert(c);
|
||||
|
||||
if (c->match)
|
||||
done = STRPTR_IN_SET(c->active_state, "inactive", "failed");
|
||||
done = STRPTR_IN_SET(c->active_state, "inactive", "failed") && !c->has_job;
|
||||
else
|
||||
done = true;
|
||||
|
||||
|
@ -1021,20 +1024,35 @@ static void run_context_check_done(RunContext *c) {
|
|||
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 const struct bus_properties_map map[] = {
|
||||
{ "ActiveState", "s", NULL, offsetof(RunContext, active_state) },
|
||||
{ "InactiveExitTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_exit_usec) },
|
||||
{ "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_enter_usec) },
|
||||
{ "Result", "s", NULL, offsetof(RunContext, result) },
|
||||
{ "ExecMainCode", "i", NULL, offsetof(RunContext, exit_code) },
|
||||
{ "ExecMainStatus", "i", NULL, offsetof(RunContext, exit_status) },
|
||||
{ "CPUUsageNSec", "t", NULL, offsetof(RunContext, cpu_usage_nsec) },
|
||||
{ "IPIngressBytes", "t", NULL, offsetof(RunContext, ip_ingress_bytes) },
|
||||
{ "IPEgressBytes", "t", NULL, offsetof(RunContext, ip_egress_bytes) },
|
||||
{ "IOReadBytes", "t", NULL, offsetof(RunContext, io_read_bytes) },
|
||||
{ "IOWriteBytes", "t", NULL, offsetof(RunContext, io_write_bytes) },
|
||||
{ "ActiveState", "s", NULL, offsetof(RunContext, active_state) },
|
||||
{ "InactiveExitTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_exit_usec) },
|
||||
{ "InactiveEnterTimestampMonotonic", "t", NULL, offsetof(RunContext, inactive_enter_usec) },
|
||||
{ "Result", "s", NULL, offsetof(RunContext, result) },
|
||||
{ "ExecMainCode", "i", NULL, offsetof(RunContext, exit_code) },
|
||||
{ "ExecMainStatus", "i", NULL, offsetof(RunContext, exit_status) },
|
||||
{ "CPUUsageNSec", "t", NULL, offsetof(RunContext, cpu_usage_nsec) },
|
||||
{ "IPIngressBytes", "t", NULL, offsetof(RunContext, ip_ingress_bytes) },
|
||||
{ "IPEgressBytes", "t", NULL, offsetof(RunContext, ip_egress_bytes) },
|
||||
{ "IOReadBytes", "t", NULL, offsetof(RunContext, io_read_bytes) },
|
||||
{ "IOWriteBytes", "t", NULL, offsetof(RunContext, io_write_bytes) },
|
||||
{ "Job", "(uo)", map_job, offsetof(RunContext, has_job) },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -531,15 +531,11 @@ int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) {
|
|||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to read LoaderTimeExecUSec: %m");
|
||||
|
||||
if (y == 0 || y < x)
|
||||
if (y == 0 || y < x || y - x > USEC_PER_HOUR)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Bad LoaderTimeInitUSec=%"PRIu64", LoaderTimeExecUSec=%" PRIu64"; refusing.",
|
||||
x, y);
|
||||
|
||||
if (y > USEC_PER_HOUR)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"LoaderTimeExecUSec=%"PRIu64" too large, refusing.", x);
|
||||
|
||||
*firmware = x;
|
||||
*loader = y;
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ int fstab_is_mount_point(const char *mount) {
|
|||
}
|
||||
|
||||
int fstab_filter_options(const char *opts, const char *names,
|
||||
const char **namefound, char **value, char **filtered) {
|
||||
const char **ret_namefound, char **ret_value, char **ret_filtered) {
|
||||
const char *name, *n = NULL, *x;
|
||||
_cleanup_strv_free_ char **stor = 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 (!filtered) {
|
||||
if (!ret_filtered) {
|
||||
const char *word, *state;
|
||||
size_t l;
|
||||
|
||||
|
@ -108,7 +108,7 @@ int fstab_filter_options(const char *opts, const char *names,
|
|||
x = word + strlen(name);
|
||||
if (IN_SET(*x, '\0', '=', ',')) {
|
||||
n = name;
|
||||
if (value) {
|
||||
if (ret_value) {
|
||||
free(v);
|
||||
if (IN_SET(*x, '\0', ','))
|
||||
v = NULL;
|
||||
|
@ -145,7 +145,7 @@ int fstab_filter_options(const char *opts, const char *names,
|
|||
found:
|
||||
/* Keep the last occurrence found */
|
||||
n = name;
|
||||
if (value) {
|
||||
if (ret_value) {
|
||||
free(v);
|
||||
if (*x == '\0')
|
||||
v = NULL;
|
||||
|
@ -162,19 +162,19 @@ int fstab_filter_options(const char *opts, const char *names,
|
|||
}
|
||||
|
||||
answer:
|
||||
if (namefound)
|
||||
*namefound = n;
|
||||
if (filtered) {
|
||||
if (ret_namefound)
|
||||
*ret_namefound = n;
|
||||
if (ret_filtered) {
|
||||
char *f;
|
||||
|
||||
f = strv_join(strv, ",");
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
*filtered = f;
|
||||
*ret_filtered = f;
|
||||
}
|
||||
if (value)
|
||||
*value = TAKE_PTR(v);
|
||||
if (ret_value)
|
||||
*ret_value = TAKE_PTR(v);
|
||||
|
||||
return !!n;
|
||||
}
|
||||
|
|
|
@ -788,19 +788,25 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
|
|||
if (!fpath)
|
||||
return log_oom();
|
||||
|
||||
service = new0(SysvStub, 1);
|
||||
log_warning("SysV service '%s' lacks a native systemd unit file. "
|
||||
"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)
|
||||
return log_oom();
|
||||
|
||||
service->sysv_start_priority = -1;
|
||||
service->name = TAKE_PTR(name);
|
||||
service->path = TAKE_PTR(fpath);
|
||||
*service = (SysvStub) {
|
||||
.sysv_start_priority = -1,
|
||||
.name = TAKE_PTR(name),
|
||||
.path = TAKE_PTR(fpath),
|
||||
};
|
||||
|
||||
r = hashmap_put(all_services, service->name, service);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
service = NULL;
|
||||
TAKE_PTR(service);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -724,7 +724,7 @@ static int run(int argc, char *argv[]) {
|
|||
last_busy_usec = n;
|
||||
else if (listen_idle_usec != USEC_INFINITY && n >= usec_add(last_busy_usec, listen_idle_usec)) {
|
||||
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));
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
# 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-fuzzers',
|
||||
output : 'sanitize-address-undefined-fuzzers',
|
||||
|
@ -7,8 +15,7 @@ sanitize_address_undefined = custom_target(
|
|||
project_source_root,
|
||||
'@OUTPUT@',
|
||||
'fuzzers',
|
||||
'-Db_lundef=false -Db_sanitize=address,undefined ' +
|
||||
'--optimization=@0@'.format(get_option('optimization')),
|
||||
'-Db_lundef=false -Db_sanitize=address,undefined @0@'.format(optimization),
|
||||
' '.join(cc.cmd_array()),
|
||||
cxx_cmd])
|
||||
|
||||
|
|
|
@ -678,6 +678,7 @@ cleanup_loopdev() {
|
|||
if [ -n "${LOOPDEV}" ]; then
|
||||
ddebug "losetup -d $LOOPDEV"
|
||||
losetup -d "${LOOPDEV}"
|
||||
unset LOOPDEV
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -698,8 +699,7 @@ create_empty_image() {
|
|||
rm -f "$IMAGE_PRIVATE" "$IMAGE_PUBLIC"
|
||||
|
||||
# Create the blank file to use as a root filesystem
|
||||
truncate -s "${_size}M" "$IMAGE_PRIVATE"
|
||||
ln -vs "$(realpath $IMAGE_PRIVATE)" "$IMAGE_PUBLIC"
|
||||
truncate -s "${_size}M" "$IMAGE_PUBLIC"
|
||||
|
||||
LOOPDEV=$(losetup --show -P -f "$IMAGE_PUBLIC")
|
||||
[ -b "$LOOPDEV" ] || return 1
|
||||
|
@ -2005,16 +2005,26 @@ test_setup() {
|
|||
if [ -e "$IMAGE_PRIVATE" ]; then
|
||||
echo "Reusing existing image $IMAGE_PRIVATE → $(realpath $IMAGE_PRIVATE)"
|
||||
mount_initdir
|
||||
elif [ -e "$IMAGE_PUBLIC" ]; then
|
||||
else
|
||||
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)"
|
||||
if [ ${TEST_PARALLELIZE} -ne 0 ]; then
|
||||
cp -v "$(realpath $IMAGE_PUBLIC)" "$IMAGE_PRIVATE"
|
||||
else
|
||||
ln -sv "$(realpath $IMAGE_PUBLIC)" "$IMAGE_PRIVATE"
|
||||
fi
|
||||
|
||||
mount_initdir
|
||||
else
|
||||
test_create_image
|
||||
fi
|
||||
|
||||
setup_nspawn_root
|
||||
|
|
|
@ -30,7 +30,9 @@ UtmpIdentifier=cons
|
|||
TTYPath=/dev/console
|
||||
TTYReset=yes
|
||||
TTYVHangup=yes
|
||||
m4_ifdef(`ENABLE_LOGIND',,
|
||||
KillMode=process
|
||||
)m4_dnl
|
||||
IgnoreSIGPIPE=no
|
||||
SendSIGHUP=yes
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@ UtmpIdentifier=pts/%I
|
|||
TTYPath=/dev/pts/%I
|
||||
TTYReset=yes
|
||||
TTYVHangup=yes
|
||||
m4_ifdef(`ENABLE_LOGIND',,
|
||||
KillMode=process
|
||||
)m4_dnl
|
||||
IgnoreSIGPIPE=no
|
||||
SendSIGHUP=yes
|
||||
|
|
|
@ -47,7 +47,9 @@ TTYPath=/dev/%I
|
|||
TTYReset=yes
|
||||
TTYVHangup=yes
|
||||
TTYVTDisallocate=yes
|
||||
m4_ifdef(`ENABLE_LOGIND',,
|
||||
KillMode=process
|
||||
)m4_dnl
|
||||
IgnoreSIGPIPE=no
|
||||
SendSIGHUP=yes
|
||||
|
||||
|
|
|
@ -40,7 +40,9 @@ UtmpIdentifier=%I
|
|||
TTYPath=/dev/%I
|
||||
TTYReset=yes
|
||||
TTYVHangup=yes
|
||||
m4_ifdef(`ENABLE_LOGIND',,
|
||||
KillMode=process
|
||||
)m4_dnl
|
||||
IgnoreSIGPIPE=no
|
||||
SendSIGHUP=yes
|
||||
|
||||
|
|
Loading…
Reference in New Issue