]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
vconsole-setup: don't fail if the only found vc is already used by plymouth
authorFranck Bui <fbui@suse.com>
Thu, 1 Feb 2024 08:13:10 +0000 (09:13 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 19 Feb 2024 08:25:14 +0000 (09:25 +0100)
During the boot process, systemd-vconsole-setup can be started when the only
allocated VC is already taken by plymouth.

This case is expected when a boot splash is displayed hence
systemd-vconsole-setup.service should not fail if it happens.

However rather than doing nothing, the sysfs utf8 flag is set before exiting
early.

src/vconsole/vconsole-setup.c

index 554d00e5b75922068c1b46f537db1d2339827b41..bc32b2267cf2ab3984fa42de92f6e6e58b93f28c 100644 (file)
@@ -521,14 +521,21 @@ static int find_source_vc(char **ret_path, unsigned *ret_idx) {
         assert(ret_path);
         assert(ret_idx);
 
+        /* This function returns an fd when it finds a candidate. When it fails, it returns the first error
+         * that occured when the VC was being opened or -EBUSY when it finds some VCs but all are busy
+         * otherwise -ENOENT when there is no allocated VC. */
+
         for (unsigned i = 1; i <= 63; i++) {
                 _cleanup_close_ int fd = -EBADF;
                 _cleanup_free_ char *path = NULL;
 
+                /* We save the first error but we give less importance for the case where we previously fail
+                 * due to the VCs being not allocated. Similarly errors on opening a device has a higher
+                 * priority than errors due to devices either not allocated or busy. */
+
                 r = verify_vc_allocation(i);
                 if (r < 0) {
-                        log_debug_errno(r, "VC %u existence check failed, skipping: %m", i);
-                        RET_GATHER(err, r);
+                        RET_GATHER(err, log_debug_errno(r, "VC %u existence check failed, skipping: %m", i));
                         continue;
                 }
 
@@ -537,29 +544,37 @@ static int find_source_vc(char **ret_path, unsigned *ret_idx) {
 
                 fd = open_terminal(path, O_RDWR|O_CLOEXEC|O_NOCTTY);
                 if (fd < 0) {
-                        RET_GATHER(err, log_debug_errno(fd, "Failed to open terminal %s, ignoring: %m", path));
+                        log_debug_errno(fd, "Failed to open terminal %s, ignoring: %m", path);
+                        if (IN_SET(err, 0, -EBUSY, -ENOENT))
+                                err = fd;
                         continue;
                 }
 
                 r = verify_vc_kbmode(fd);
                 if (r < 0) {
-                        RET_GATHER(err, log_debug_errno(r, "Failed to check VC %s keyboard mode: %m", path));
+                        log_debug_errno(r, "Failed to check VC %s keyboard mode: %m", path);
+                        if (IN_SET(err, 0, -ENOENT))
+                                err = r;
                         continue;
                 }
 
                 r = verify_vc_display_mode(fd);
                 if (r < 0) {
-                        RET_GATHER(err, log_debug_errno(r, "Failed to check VC %s display mode: %m", path));
+                        log_debug_errno(r, "Failed to check VC %s display mode: %m", path);
+                        if (IN_SET(err, 0, -ENOENT))
+                                err = r;
                         continue;
                 }
 
+                log_debug("Selecting %s as source console", path);
+
                 /* all checks passed, return this one as a source console */
                 *ret_idx = i;
                 *ret_path = TAKE_PTR(path);
                 return TAKE_FD(fd);
         }
 
-        return log_error_errno(err, "No usable source console found: %m");
+        return err;
 }
 
 static int verify_source_vc(char **ret_path, const char *src_vc) {
@@ -610,14 +625,26 @@ static int run(int argc, char **argv) {
 
         umask(0022);
 
-        if (argv[1])
+        if (argv[1]) {
                 fd = verify_source_vc(&vc, argv[1]);
-        else
+                if (fd < 0)
+                        return fd;
+        } else {
                 fd = find_source_vc(&vc, &idx);
-        if (fd < 0)
-                return fd;
+                if (fd < 0 && fd != -EBUSY)
+                        return log_error_errno(fd, "No usable source console found: %m");
+        }
 
         utf8 = is_locale_utf8();
+        (void) toggle_utf8_sysfs(utf8);
+
+        if (fd < 0) {
+                /* We found only busy VCs, which might happen during the boot process when the boot splash is
+                 * displayed on the only allocated VC. In this case we don't interfer and avoid initializing
+                 * the VC partially as some operations are likely to fail. */
+                log_notice("All allocated VCs are currently busy, skipping initialization of font and keyboard settings.");
+                return EXIT_SUCCESS;
+        }
 
         context_load_config(&c);
 
@@ -629,7 +656,6 @@ static int run(int argc, char **argv) {
         else if (lock_fd < 0)
                 return log_error_errno(lock_fd, "Failed to lock /dev/console: %m");
 
-        (void) toggle_utf8_sysfs(utf8);
         (void) toggle_utf8_vc(vc, fd, utf8);
 
         r = font_load_and_wait(vc, &c);