Hey folks,
I've been looking into some "system integration" issues that have always bothered me during my spare time.
Among the biggest and most frustrating of these is the TTY cursor briefly showing up whenever you suspend/resume your machine and log off/switch sessions.
After tinkering for a bit, I managed to narrow down what caused this. Whenever the system performs any of these actions, it appears to briefly switch to /dev/tty1, where GDM (or another display manager) is running. However, the display manager is not active, so the system falls back to showing the TTY console. Since the cursor is on by default for all TTYs, including the first one, the user will briefly see a black screen with nothing but the blinking cursor.
/dev/tty1
So, how do we fix this?
Disabling the TTY cursor by default is not an option because it'd either require the kernel parameters or build arguments to be changed. This would also affect all other TTYs, which should have cursors.
So here's the approach I took for prototyping a "fix". I created a systemd service which uses setterm on /dev/tty1 to disable the cursor, then modified gdm to depend on that service:
setterm
# /etc/systemd/system/disable-tty-cursor.service [Unit] Description=Disable TTY1 cursor [Service] Type=oneshot StandardInput=tty StandardOutput=tty TTYPath=/dev/tty1 Environment=TERM=linux ExecStart=/usr/bin/setterm --cursor off
# /etc/systemd/system/gdm.service.d/tty-cursor-fix.conf [Unit] Requires=disable-tty-cursor.service
This keeps the cursor visible during the boot process (when the user presses "ESC" while Plymouth is running to see the TTY), but its hidden before starting gdm, making suspend, resume and logging out seamless - the screen is black during the transition, with no visual glitches.
I'd like to know your thoughts on where this belongs. Should this be brought up with upstream, or is this something to be implemented downstream in Fedora?
Thanks in advance.
Looks like some additional steps are required for suspend/resume. VT seems to use whatever the kernel's defaults are, instead of TTY1's configuration.
Luckily, I found a really nasty hack which fixes this issue. You can bind and unbind the VT during runtime (effectively disabling it), so if we disable VT before suspend and re-enable it after, the cursor will no longer be visible:
# /etc/systemd/system/vt-suspend.service [Unit] Description=Suspend VT Before=systemd-suspend.service [Service] Type=oneshot ExecStart=/usr/bin/sh -c "echo 0 > /sys/devices/virtual/vtconsole/vtcon1/bind" [Install] WantedBy=systemd-suspend.service
# /etc/systemd/system/vt-resume.service [Unit] Description=Resume VT After=systemd-suspend.service [Service] Type=oneshot ExecStart=/usr/bin/sh -c "echo 1 > /sys/devices/virtual/vtconsole/vtcon1/bind" [Install] WantedBy=systemd-suspend.service
@rstrode @jadahl we might need your opinions on this one
maybe gdm should put the console in KD_GRAPHICS mode before jumping to it in its jump_to_vt function
I've found a better fix for the "console cursor" suspend issue.
This appears to be part of the suspend behavior with the kernel console: https://github.com/torvalds/linux/blob/master/kernel/power/console.c#L46
The kernel may switch to a different VT (defined as SUSPEND_CONSOLE) when suspending the console, depending on the graphics driver. It then restores the console when resuming.
SUSPEND_CONSOLE
The blinking cursor belongs to the suspend VT. Disabling the cursor of that console results in a black screen during the transition, which is better than the current behavior:
[Unit] Description=Disable suspend console cursor [Service] Type=oneshot StandardInput=tty StandardOutput=tty TTYPath=/dev/tty63 Environment=TERM=linux ExecStart=/usr/bin/setterm --cursor off [Install] WantedBy=display-manager.service
I'm stumped, honestly. The VT switch isn't supposed to be triggering with my hardware... but, in any case, this should make the experience better for users which need this workaround.
Log in to comment on this ticket.