Compare commits

...

24 Commits

Author SHA1 Message Date
Lennart Poettering 49d5aae503
Merge pull request #15934 from keszybz/docs-and-test-fix
A few sundry documentation and code fixes
2020-05-27 15:16:24 +02:00
Lennart Poettering 6d02412d51
Merge pull request #15928 from poettering/kill-mode-warnings
warn on KillMode=none, inform about left-over processes on stop and warn about sysv services
2020-05-27 15:05:41 +02:00
Chris Kerr 8aa36b1ddd man: Fix typo in suggested permissions
The user and group name is 'systemd-network' not 'systemd-networkd'
2020-05-27 15:03:25 +02:00
Lennart Poettering 2b5f708985 run: when waiting for unit, also check if no job is pending anymore
This is a fix-up for a7c71d214c37797d82de2f66cfe0a0a79c3a5c92: since we
now don't wait for the job to finish anymore right after enqueuing it,
we should not exit our ptyfwd logic before the unit is back to inactive
*and* no job pending anymore.
2020-05-27 15:01:07 +02:00
Lennart Poettering 518a9bd689
Merge pull request #15853 from poettering/tmp-argument
support the Debian-style tmp= argument in crypttab
2020-05-27 14:51:50 +02:00
Frantisek Sumsal ffbb0fb9cb meson: support building fuzzers with meson <0.48.0 2020-05-27 12:27:45 +02:00
Chris Down 4793c31083 service: Display updated WatchdogUSec from sd_notify
Suppose a service has WatchdogSec set to 2 seconds in its unit file. I
then start the service and WatchdogUSec is set correctly:

    % systemctl --user show psi-notify -p WatchdogUSec
    WatchdogUSec=2s

Now I call `sd_notify(0, "WATCHDOG_USEC=10000000")`. The new timer seems
to have taken effect, since I only send `WATCHDOG=1` every 4 seconds,
and systemd isn't triggering the watchdog handler. However, `systemctl
show` still shows WatchdogUSec as 2s:

    % systemctl --user show psi-notify -p WatchdogUSec
    WatchdogUSec=2s

This seems surprising, since this "original" watchdog timer isn't the
one taking effect any more. This patch makes it so that we instead
display the new watchdog timer after sd_notify(WATCHDOG_USEC):

    % systemctl --user show psi-notify -p WatchdogUSec
    WatchdogUSec=10s

Fixes #15726.
2020-05-27 09:09:40 +02:00
Zbigniew Jędrzejewski-Szmek dde5c821bf shared/efi-loader: remove check that uses absolute tick value
sd-boot uses rdtsc to set those timestamps. There is no guarantee that the tsc
has any particular absolute value.

On my VM:
$ head /sys/firmware/efi/efivars/LoaderTime*
==> /sys/firmware/efi/efivars/LoaderTimeExecUSec-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f <==
4397904074
==> /sys/firmware/efi/efivars/LoaderTimeInitUSec-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f <==
4396386839
==> /sys/firmware/efi/efivars/LoaderTimeMenuUSec-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f <==
4396392521

$ build/test-boot-timestamps
...
LoaderTimeExecUSec=4396386839 too large, refusing.
Failed to read EFI loader data: Input/output error
Assertion 'q >= 0' failed at src/test/test-boot-timestamps.c:84, function main(). Aborting.

(with patch)
$ build/test-boot-timestamps
...
EFI Loader: start=1h 13min 16.386s exit=1h 13min 17.904s duration=1.517s
Firmware began 1h 13min 17.904074s before kernel.
Loader began 1.517235s before kernel.
Firmware began Tue 2020-05-26 11:04:13 CEST.
Loader began Tue 2020-05-26 12:17:30 CEST.
Kernel began Tue 2020-05-26 12:17:31 CEST.
2020-05-27 09:02:53 +02:00
Zbigniew Jędrzejewski-Szmek 24b4597064 core: minor simplification 2020-05-27 09:02:53 +02:00
Zbigniew Jędrzejewski-Szmek 40fd0a77c6 userwork: remove trailing comma in message 2020-05-27 09:02:53 +02:00
Zbigniew Jędrzejewski-Szmek 1414090854 core: add forgotten return in error path
If we get an error here, this is most likely oom, and we should not continue.
2020-05-27 09:02:53 +02:00
Zbigniew Jędrzejewski-Szmek 3035a7c577 core: update comment about sysv compat
We don't want people to consider that part deprecated.

Follow-up for 6589a56972.
2020-05-27 09:02:09 +02:00
Frantisek Sumsal 2991fa41e4 test: create public images by default
Let's create new images public by default and then symlink/copy them
into the respective private directories afterwards, not the other way
around. This should fix a nasty race condition in parallel runs where
one tests attempts to copy the backing public image at the same moment
another test is already modifying it.
2020-05-27 08:41:02 +02:00
Lennart Poettering effefa30de update TODO 2020-05-26 23:52:34 +02:00
Lennart Poettering 0e42cbe254 sysv: generate warning for every SysV service lacking a native systemd unit
It's 2020, let's tighten the screws a bit and start warning about
left-over SysV services that still have no native systemd unit file.
2020-05-26 23:52:30 +02:00
Lennart Poettering 470ab28d07 sysv: use structured initialization 2020-05-26 23:52:26 +02:00
Lennart Poettering c8aa4b5b86 core: voidify one function return 2020-05-26 23:52:22 +02:00
Lennart Poettering b0cea477d4 core: some more structured initialization 2020-05-26 23:52:18 +02:00
Lennart Poettering 4c42543429 core: also log about left-over processes during unit stop
Only log at LOG_INFO level, i.e. make this informational. During start
let's leave it at LOG_WARNING though.

Of course, it's ugly leaving processes around like that either in start
or in stop, but at start its more dangerous than on stop, so be tougher
there.
2020-05-26 23:52:13 +02:00
Lennart Poettering 021acbc188 units: remove KillMode=process in our regular gettys
In our regular gettys the actual shell commands live the the session
scope anyway (as long as logind is used). Hence, let's avoid
KillMode=process, it serves no purpose and is simply unsafe since it
disables systemd's own process lifecycle management.
2020-05-26 23:52:09 +02:00
Lennart Poettering 9b52e0d81a man: document that KillMode=none is a bad idea 2020-05-26 23:51:51 +02:00
Lennart Poettering d068765b68 core: warn if KillMode=none is used 2020-05-26 23:50:54 +02:00
Lennart Poettering 53ac130b51 cryptsetup: support tmp= file system argument
Let's catch up with Debian a bit more.

This also changes the default from ext2 to ext4.

Fixes: #952
2020-05-26 17:11:34 +02:00
Lennart Poettering 92a08691c2 fstab-util: prefix return parameters with ret_ 2020-05-26 17:10:54 +02:00
28 changed files with 253 additions and 137 deletions

2
TODO
View File

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

View File

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

View File

@ -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_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,
@ -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("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", 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), 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,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_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");
@ -631,6 +630,48 @@ 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,
@ -4782,7 +4823,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)
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, 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;
/* SysV compatibility */ /* Compatible with SysV, but supported independently even if SysV compatiblity is disabled. */
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,18 +679,12 @@ static int manager_setup_prefix(Manager *m) {
[EXEC_DIRECTORY_CONFIGURATION] = { SD_PATH_USER_CONFIGURATION, NULL }, [EXEC_DIRECTORY_CONFIGURATION] = { SD_PATH_USER_CONFIGURATION, NULL },
}; };
const struct table_entry *p;
ExecDirectoryType i;
int r;
assert(m); assert(m);
if (MANAGER_IS_SYSTEM(m)) const struct table_entry *p = MANAGER_IS_SYSTEM(m) ? paths_system : paths_user;
p = paths_system; int r;
else
p = paths_user;
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]); r = sd_path_lookup(p[i].type, p[i].suffix, &m->prefix[i]);
if (r < 0) if (r < 0)
return r; return r;
@ -1344,15 +1338,12 @@ 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 (c = 0; c < _UNIT_TYPE_MAX; c++) for (UnitType 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);
@ -1423,22 +1414,20 @@ 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 (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]); 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 (c = 0; c < _UNIT_TYPE_MAX; c++) { for (UnitType 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;
@ -1450,15 +1439,13 @@ 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 (c = 0; c < _UNIT_TYPE_MAX; c++) { for (UnitType 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,6 +863,8 @@ 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);
@ -1008,7 +1010,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_warn_leftover_processes(UNIT(m), unit_log_leftover_process_start);
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,15 +198,6 @@ 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;
@ -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) if (!fs)
return -ENOMEM; return -ENOMEM;
fs->fd = fd; *fs = (ServiceFDStore) {
fs->service = s; .fd = fd,
fs->do_poll = do_poll; .service = s,
fs->fdname = strdup(name ?: "stored"); .do_poll = do_poll,
.fdname = strdup(name ?: "stored"),
};
if (!fs->fdname) { if (!fs->fdname) {
free(fs); free(fs);
return -ENOMEM; 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)); 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.");
@ -2081,15 +2076,16 @@ 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 * service where a SigKilled process would result in a lengthy recovery and who's shutdown or startup
* startup time is quite variable (so Timeout settings aren't of use). * 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,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; 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,6 +2035,8 @@ 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);
@ -2237,7 +2239,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_warn_leftover_processes(UNIT(s), unit_log_leftover_process_start);
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,6 +701,7 @@ 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);
@ -788,7 +789,7 @@ static void swap_enter_activating(Swap *s) {
assert(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_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,7 +4971,7 @@ int unit_kill_context(
if (!pid_set) if (!pid_set)
return -ENOMEM; return -ENOMEM;
cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, (void) cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
SIGHUP, SIGHUP,
CGROUP_IGNORE_SELF, CGROUP_IGNORE_SELF,
pid_set, pid_set,
@ -5861,14 +5861,20 @@ int unit_prepare_exec(Unit *u) {
return 0; 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; _cleanup_free_ char *comm = NULL;
(void) get_process_comm(pid, &comm); (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; 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.",
@ -5877,7 +5883,24 @@ static int log_leftover(pid_t pid, int sig, void *userdata) {
return 1; 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); assert(u);
(void) unit_pick_cgroup_path(u); (void) unit_pick_cgroup_path(u);
@ -5885,7 +5908,7 @@ int unit_warn_leftover_processes(Unit *u) {
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_leftover, u); return cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, 0, 0, NULL, log_func, u);
} }
bool unit_needs_console(Unit *u) { bool unit_needs_console(Unit *u) {

View File

@ -846,7 +846,9 @@ void unit_unlink_state_files(Unit *u);
int unit_prepare_exec(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); 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, tmp, swap, netdev, attach_in_initrd; bool noauto, nofail, swap, netdev, attach_in_initrd;
int r, detached_header, keyfile_can_timeout; int r, detached_header, keyfile_can_timeout, tmp;
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,6 +261,10 @@ 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.",
@ -371,10 +375,19 @@ 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 ext2 '/dev/mapper/%s'\n", "ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs '%s' '/dev/mapper/%s'\n",
name_escaped); tmp_fstype_escaped ?: "ext4", name_escaped);
}
if (swap) if (swap)
fprintf(f, fprintf(f,

View File

@ -78,7 +78,6 @@ STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_uri, freep);
loud loud
quiet quiet
keyscript= keyscript=
tmp= (the version without argument is supported)
initramfs initramfs
*/ */
@ -232,7 +231,8 @@ 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,8 +978,11 @@ typedef struct RunContext {
PTYForward *forward; PTYForward *forward;
sd_bus_slot *match; sd_bus_slot *match;
/* The exit data of the unit */ /* Current state of the unit */
char *active_state; char *active_state;
bool has_job;
/* The exit data of the unit */
uint64_t inactive_exit_usec; uint64_t inactive_exit_usec;
uint64_t inactive_enter_usec; uint64_t inactive_enter_usec;
char *result; char *result;
@ -1010,7 +1013,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"); done = STRPTR_IN_SET(c->active_state, "inactive", "failed") && !c->has_job;
else else
done = true; done = true;
@ -1021,6 +1024,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[] = {
@ -1035,6 +1052,7 @@ static int run_context_update(RunContext *c, const char *path) {
{ "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,15 +531,11 @@ 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) if (y == 0 || y < x || y - x > USEC_PER_HOUR)
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 **namefound, char **value, char **filtered) { const char **ret_namefound, char **ret_value, char **ret_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 (!filtered) { if (!ret_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 (value) { if (ret_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 (value) { if (ret_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 (namefound) if (ret_namefound)
*namefound = n; *ret_namefound = n;
if (filtered) { if (ret_filtered) {
char *f; char *f;
f = strv_join(strv, ","); f = strv_join(strv, ",");
if (!f) if (!f)
return -ENOMEM; return -ENOMEM;
*filtered = f; *ret_filtered = f;
} }
if (value) if (ret_value)
*value = TAKE_PTR(v); *ret_value = TAKE_PTR(v);
return !!n; return !!n;
} }

View File

@ -788,19 +788,25 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
if (!fpath) if (!fpath)
return log_oom(); 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) if (!service)
return log_oom(); return log_oom();
service->sysv_start_priority = -1; *service = (SysvStub) {
service->name = TAKE_PTR(name); .sysv_start_priority = -1,
service->path = TAKE_PTR(fpath); .name = TAKE_PTR(name),
.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();
service = NULL; TAKE_PTR(service);
} }
} }

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,5 +1,13 @@
# 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',
@ -7,8 +15,7 @@ sanitize_address_undefined = custom_target(
project_source_root, project_source_root,
'@OUTPUT@', '@OUTPUT@',
'fuzzers', 'fuzzers',
'-Db_lundef=false -Db_sanitize=address,undefined ' + '-Db_lundef=false -Db_sanitize=address,undefined @0@'.format(optimization),
'--optimization=@0@'.format(get_option('optimization')),
' '.join(cc.cmd_array()), ' '.join(cc.cmd_array()),
cxx_cmd]) cxx_cmd])

View File

@ -678,6 +678,7 @@ 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
} }
@ -698,8 +699,7 @@ 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_PRIVATE" truncate -s "${_size}M" "$IMAGE_PUBLIC"
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,16 +2005,26 @@ 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
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)" 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,7 +30,9 @@ 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,6 +36,8 @@ 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,7 +47,9 @@ 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,7 +40,9 @@ 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