diff --git a/man/systemd-vconsole-setup.service.xml b/man/systemd-vconsole-setup.service.xml index e462ef8f603..d156c482db9 100644 --- a/man/systemd-vconsole-setup.service.xml +++ b/man/systemd-vconsole-setup.service.xml @@ -32,14 +32,17 @@ Description - systemd-vconsole-setup sets up and configures either all virtual consoles, or — if the - optional TTY parameter is provided — a specific one. When the system is booting up, it's - called by systemd-udevd8 during - VT console subsystem initialization. Also, - systemd-localed.service8 invokes - it as needed when language or console changes are made. Internally, this program calls loadkeys1 and setfont8. + systemd-vconsole-setup sets up and configures either all virtual consoles, or + — if the optional TTY parameter is provided — a specific one. When the system + is booting up, systemd-vconsole-setup.service is called by + systemd-udevd8 during + VT console subsystem initialization. Also, + systemd-localed.service8 + invokes it as needed when language or console changes are made. + Internally, this program calls + loadkeys1 + and + setfont8. Execute systemctl restart systemd-vconsole-setup.service in order to apply any manual diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index e0774073677..c3df4166d55 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -70,12 +70,8 @@ Units whose standard output or error output is connected to or (or their combinations with console output, see below) automatically acquire - dependencies of type After= on systemd-journald.socket. - - - Units using the terminal (standard input, output, or error are connected to a terminal - or TTYPath= is used) automatically acquire an After= dependency - on systemd-vconsole-setup.service. + dependencies of type After= on + systemd-journald.socket. Units using LogNamespace= will automatically gain ordering and requirement dependencies on the two socket units associated with diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 94c0dfd3de5..804440ef2a5 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -1172,7 +1172,6 @@ int xopenat_lock( int r; assert(dir_fd >= 0 || dir_fd == AT_FDCWD); - assert(path); assert(IN_SET(operation & ~LOCK_NB, LOCK_EX, LOCK_SH)); /* POSIX/UNPOSIX locks don't work on directories (errno is set to -EBADF so let's return early with diff --git a/src/basic/special.h b/src/basic/special.h index bc9c9eb011c..b7760079a27 100644 --- a/src/basic/special.h +++ b/src/basic/special.h @@ -86,7 +86,6 @@ #define SPECIAL_QUOTACHECK_SERVICE "systemd-quotacheck.service" #define SPECIAL_QUOTAON_SERVICE "quotaon.service" #define SPECIAL_REMOUNT_FS_SERVICE "systemd-remount-fs.service" -#define SPECIAL_VCONSOLE_SETUP_SERVICE "systemd-vconsole-setup.service" #define SPECIAL_VOLATILE_ROOT_SERVICE "systemd-volatile-root.service" #define SPECIAL_UDEVD_SERVICE "systemd-udevd.service" #define SPECIAL_GROWFS_SERVICE "systemd-growfs@.service" diff --git a/src/core/execute.c b/src/core/execute.c index c2958b4bd29..067f7bdb8bd 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -229,25 +229,34 @@ static int exec_context_tty_size(const ExecContext *context, unsigned *ret_rows, } static void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p) { - const char *path; + _cleanup_close_ int fd = -EBADF; + const char *path = exec_context_tty_path(ASSERT_PTR(context)); - assert(context); + /* Take a lock around the device for the duration of the setup that we do here. + * systemd-vconsole-setup.service also takes the lock to avoid being interrupted. + * We open a new fd that will be closed automatically, and operate on it for convenience. + */ - path = exec_context_tty_path(context); + if (p && p->stdin_fd >= 0) { + fd = xopenat_lock(p->stdin_fd, NULL, + O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY, 0, 0, LOCK_BSD, LOCK_EX); + if (fd < 0) + return; + } else if (path) { + fd = open_terminal(path, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK); + if (fd < 0) + return; - if (context->tty_vhangup) { - if (p && p->stdin_fd >= 0) - (void) terminal_vhangup_fd(p->stdin_fd); - else if (path) - (void) terminal_vhangup(path); - } + if (lock_generic(fd, LOCK_BSD, LOCK_EX) < 0) + return; + } else + return; /* nothing to do */ - if (context->tty_reset) { - if (p && p->stdin_fd >= 0) - (void) reset_terminal_fd(p->stdin_fd, true); - else if (path) - (void) reset_terminal(path); - } + if (context->tty_vhangup) + (void) terminal_vhangup_fd(fd); + + if (context->tty_reset) + (void) reset_terminal_fd(fd, true); if (p && p->stdin_fd >= 0) { unsigned rows = context->tty_rows, cols = context->tty_cols; @@ -7180,16 +7189,6 @@ bool exec_context_has_encrypted_credentials(ExecContext *c) { return false; } -int exec_context_add_default_dependencies(Unit *u, const ExecContext *c) { - assert(u); - assert(u->default_dependencies); - - if (c && exec_context_needs_term(c)) - return unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_VCONSOLE_SETUP_SERVICE, - /* add_reference= */ true, UNIT_DEPENDENCY_DEFAULT); - return 0; -} - void exec_status_start(ExecStatus *s, pid_t pid) { assert(s); diff --git a/src/core/execute.h b/src/core/execute.h index 09f007bb4e9..f784c1a5652 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -501,7 +501,6 @@ void exec_context_revert_tty(ExecContext *c); int exec_context_get_clean_directories(ExecContext *c, char **prefix, ExecCleanMask mask, char ***ret); int exec_context_get_clean_mask(ExecContext *c, ExecCleanMask *ret); -int exec_context_add_default_dependencies(Unit *u, const ExecContext *c); void exec_status_start(ExecStatus *s, pid_t pid); void exec_status_exit(ExecStatus *s, const ExecContext *context, pid_t pid, int code, int status); diff --git a/src/core/mount.c b/src/core/mount.c index 1e752aa44ff..70c8f088a09 100644 --- a/src/core/mount.c +++ b/src/core/mount.c @@ -601,7 +601,7 @@ static int mount_add_default_dependencies(Mount *m) { if (r < 0) return r; - return exec_context_add_default_dependencies(UNIT(m), &m->exec_context); + return 0; } static int mount_verify(Mount *m) { diff --git a/src/core/service.c b/src/core/service.c index 8e1b227a8bf..1b0af40b411 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -747,12 +747,7 @@ static int service_add_default_dependencies(Service *s) { return r; /* Third, add us in for normal shutdown. */ - r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT); - if (r < 0) - return r; - - /* Fourth, add generic dependencies */ - return exec_context_add_default_dependencies(UNIT(s), &s->exec_context); + return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT); } static void service_fix_stdio(Service *s) { diff --git a/src/core/socket.c b/src/core/socket.c index e4c1f5a793f..d72194f20b5 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -283,11 +283,7 @@ static int socket_add_default_dependencies(Socket *s) { return r; } - r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT); - if (r < 0) - return r; - - return exec_context_add_default_dependencies(UNIT(s), &s->exec_context); + return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, true, UNIT_DEPENDENCY_DEFAULT); } _pure_ static bool socket_has_exec(Socket *s) { diff --git a/src/core/swap.c b/src/core/swap.c index 6fc5782bc8c..37642a64a61 100644 --- a/src/core/swap.c +++ b/src/core/swap.c @@ -270,11 +270,7 @@ static int swap_add_default_dependencies(Swap *s) { if (r < 0) return r; - r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, UNIT_DEPENDENCY_DEFAULT); - if (r < 0) - return r; - - return exec_context_add_default_dependencies(UNIT(s), &s->exec_context); + return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, UNIT_DEPENDENCY_DEFAULT); } static int swap_verify(Swap *s) { diff --git a/src/shared/exit-status.c b/src/shared/exit-status.c index 623adda89e7..0ac688b7635 100644 --- a/src/shared/exit-status.c +++ b/src/shared/exit-status.c @@ -145,12 +145,11 @@ bool is_clean_exit(int code, int status, ExitClean clean, const ExitStatusSet *s bitmap_isset(&success_status->status, status)); /* If a daemon does not implement handlers for some of the signals, we do not consider this an - unclean shutdown */ + * unclean shutdown */ if (code == CLD_KILLED) - return - (clean == EXIT_CLEAN_DAEMON && IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE)) || - (success_status && - bitmap_isset(&success_status->signal, status)); + return (clean == EXIT_CLEAN_DAEMON && IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE)) || + (success_status && + bitmap_isset(&success_status->signal, status)); return false; } diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index 0c63f73bcf8..1d5ee9ad442 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -26,6 +26,7 @@ #include "fileio.h" #include "io-util.h" #include "locale-util.h" +#include "lock-util.h" #include "log.h" #include "proc-cmdline.h" #include "process-util.h" @@ -589,6 +590,14 @@ int main(int argc, char **argv) { context_load_config(&c); + /* Take lock around the remaining operation to avoid being interrupted by a tty reset operation + * performed for services with TTYVHangup=yes. */ + r = lock_generic(fd, LOCK_BSD, LOCK_EX); + if (r < 0) { + log_error_errno(r, "Failed to lock console: %m"); + return EXIT_FAILURE; + } + (void) toggle_utf8_sysfs(utf8); (void) toggle_utf8_vc(vc, fd, utf8); diff --git a/units/systemd-firstboot.service b/units/systemd-firstboot.service index 0c8d574ef8b..78a408708b2 100644 --- a/units/systemd-firstboot.service +++ b/units/systemd-firstboot.service @@ -15,7 +15,14 @@ ConditionPathIsReadWrite=/etc ConditionFirstBoot=yes DefaultDependencies=no -After=systemd-remount-fs.service systemd-sysusers.service systemd-tmpfiles-setup.service +# This service may need to write to the file system: +After=systemd-remount-fs.service +# Both systemd-sysusers and systemd-tmpfiles may create the root account +# (via factory files or credentials), obviating the need for us to do that: +After=systemd-sysusers.service systemd-tmpfiles-setup.service +# Let vconsole-setup do its setup before starting user interaction: +After=systemd-vconsole-setup.service + Wants=first-boot-complete.target Before=first-boot-complete.target sysinit.target Conflicts=shutdown.target diff --git a/units/systemd-vconsole-setup.service.in b/units/systemd-vconsole-setup.service.in index 0604ed0173c..96417e19bda 100644 --- a/units/systemd-vconsole-setup.service.in +++ b/units/systemd-vconsole-setup.service.in @@ -8,7 +8,7 @@ # (at your option) any later version. [Unit] -Description=Setup Virtual Console +Description=Virtual Console Setup Documentation=man:systemd-vconsole-setup.service(8) man:vconsole.conf(5) ConditionPathExists=/dev/tty0 @@ -19,6 +19,12 @@ Before=initrd-switch-root.target shutdown.target [Service] Type=oneshot +# This service will be restarted by udev whenever a new vtcon device appears. +# If the previous instance is still running, it shall be interrupted without +# error. +SuccessExitStatus=SIGTERM RemainAfterExit=yes + ExecStart={{ROOTLIBEXECDIR}}/systemd-vconsole-setup + ImportCredential=vconsole.*