Posts in category “Linux”

Remote desktop taskbar won't click, but the terminal still types? A mouse button is stuck down

Over xrdp (Remmina client, XFCE session), the taskbar and every window suddenly ignored clicks. The terminal still took keystrokes. Nothing was hung, and memory was fine.

The cause: the RDP link dropped a mouse button release event. When you press a mouse button, X gives the pointer to the window under it until the button comes up. That is an implicit grab. If the release never arrives, that window keeps the pointer forever, and every other client stops getting clicks.

You can confirm it in two steps. First, ask X which buttons it thinks are down:

export DISPLAY=:10.0          # your xrdp display
xinput list                   # find the xrdpMouse id
xinput query-state 6 | grep down
#   button[3]=down             <- right button stuck

Then make Xorg log who holds the grab by sending the XF86LogGrabInfo keysym. Map it to a free keycode for a moment if it isn't bound:

xmodmap -e "keycode 255 = XF86LogGrabInfo"
xdotool key XF86LogGrabInfo   # or an XTest fake key event
xmodmap -e "keycode 255 ="
grep -A6 'currently active device grabs' ~/.xorgxrdp.10.log
#   Active grab ... on device 'Virtual core pointer'
#   client pid 2491417 xfce4-terminal  (implicit)

The fix is to click the stuck button once inside the remote session. In this case that was a single right-click. The real press and release reach xrdpMouse, the button state clears, and the grab goes away.

Faking the release locally with XTestFakeButtonEvent does not work. It comes from the XTEST device, while the stuck state belongs to the xrdpMouse device. If clicking can't fix it, closing the window that holds the grab also releases it.

The trigger is usually pressing a button just as focus leaves the Remmina window, or an RDP reconnect in the middle of a click.

Chromebook on Linux: Search + top row as media keys, without losing F1–F12

On a Chromebook running Linux, the top row sends plain F1–F10, so brightness and volume keys do nothing. Most remap scripts flip it: media keys by default and Search for F-keys. That makes Ctrl+Alt+F1 a four-key chord. Doing it the other way keeps both: F-keys by default, and Search acts like Fn.

Install keyd (it's packaged in Debian 13) and write /etc/keyd/default.conf:

# internal keyboard only (vendor:product of "AT Translated Set 2 keyboard")
[ids]
0001:0001

# Search is leftmeta; holding it turns the top row into Chromebook actions
[meta]
f1 = back
f2 = forward
f3 = refresh
f4 = f11
f6 = brightnessdown
f7 = brightnessup
f8 = mute
f9 = volumedown
f10 = volumeup

Then restart it:

sudo systemctl restart keyd
sudo journalctl -u keyd -b -o cat | grep match

You should see a DEVICE: match 0001:0001:... line. One gotcha: the Debian package starts keyd as soon as it's installed, before your config exists. The running daemon then logs ignoring for every device until you restart it. Debian also ships the binary as keyd.rvaiya, so keyd check isn't on your PATH.

Restricting [ids] to the built-in keyboard leaves an external USB keyboard's real F-keys alone. You can find your IDs with grep -A4 'AT Translated' /proc/bus/input/devices. The mapping above matches the classic Chromebook top row (back, forward, refresh, fullscreen, overview, brightness −/+, mute, volume −/+).

Old Bay Trail laptop dies with the lid closed and leaves no logs? Cap the C-states

My Linux Chromebook (Celeron N2840, Bay Trail) kept "turning itself off" while the lid was closed. When I opened it the screen was black, and only a long press on Power brought it back. I never shut it down, and the lid action was set to "display off" rather than suspend.

The journal confirmed every boot ended without any shutdown sequence:

journalctl --list-boots
sudo journalctl -b -1 -n 30 --no-pager

The previous boots just stopped. earlyoom logs a line every minute, and that line simply ended. Nothing else was there either: no oops, nothing in /var/lib/systemd/pstore/, memory and temperatures fine. A hard freeze that writes nothing, and only while the machine is idle, is the classic Bay Trail deep C-state bug (kernel bugzilla 109051). It still shows up on a 6.12 kernel.

The usual workaround is to keep the CPU out of the deep idle states:

sudo sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"$/GRUB_CMDLINE_LINUX_DEFAULT="quiet splash intel_idle.max_cstate=1"/' /etc/default/grub
sudo update-grub

After a reboot, check it took:

cat /sys/module/intel_idle/parameters/max_cstate      # 1
cat /sys/devices/system/cpu/cpu0/cpuidle/state*/name  # only POLL and C1

The cost is a little more idle power, which hardly matters on AC. If it still freezes, add processor.max_cstate=1 as well.

While I was in there, I found that MX Linux had installed broadcom-sta-dkms, and its wl module was loading on a machine with Intel wifi. That tainted the kernel and printed a WARNING at boot. If lspci shows no Broadcom card, blacklist it:

printf 'blacklist wl\n' | sudo tee /etc/modprobe.d/no-wl.conf
sudo update-initramfs -u

A self-hosted runner can be offline while its server is online

A machine can have normal network connectivity while GitHub Actions sees its self-hosted runner as offline. The runner listener is a separate process, and GitHub may delete a registration after it has been disconnected for a long time. The local .runner file and systemd unit can still remain, which makes the failure easy to miss.

Make ordinary crashes and reboots self-healing with a systemd drop-in:

[Unit]
StartLimitIntervalSec=0

[Service]
Restart=always
RestartSec=10s

Then reload systemd and restart the runner. Check both systemctl is-active locally and the runner status in GitHub. If the log says the registration was deleted or asks you to re-configure, a restart is not enough: obtain a fresh registration token and run config.sh --replace before enabling the service again.

Home server drops off the network but stays up? Check for an e1000e "Hardware Unit Hang"

My always-on home server, an old Dell Latitude with an Intel 82579LM NIC, went silent for 22 minutes. The machine itself was fine. A reboot brought the network back, but a reboot doesn't tell you why it went down.

The kernel log from the previous boot does:

sudo journalctl -k -b -1 | grep -c "Detected Hardware Unit Hang"
sudo journalctl -k -b -1 | grep "Hardware Unit Hang" | sed -n '1p;$p'

There were 678 hits, two seconds apart, from the moment it dropped until I rebooted. The TX descriptor ring was stuck (TDH never moved), and the driver never managed to reset the card. The NIC simply stopped transmitting.

This is a long-known e1000e erratum on 82579/82574-era Intel NICs. The usual trigger is TCP segmentation offload. The standard mitigation is to stop the card doing TSO/GSO and let the CPU do it, which costs almost nothing at home-network speeds:

sudo apt install ethtool
sudo ethtool -K eno1 tso off gso off
sudo ethtool -k eno1 | grep -E '^(tcp-segmentation|generic-segmentation)-offload'

ethtool -K doesn't survive a reboot. If NetworkManager owns the interface, you don't need a udev rule or a systemd unit: NM can apply ethtool features itself on every activation:

sudo nmcli con modify "Wired connection 1" ethtool.feature-tso off ethtool.feature-gso off
nmcli -g ethtool.feature-tso,ethtool.feature-gso con show "Wired connection 1"

Applying it live only blips the link for a second, so it's safe even when you're working over that same connection, or from a VM running on the box.

If the hang ever comes back with offload off, the next suspects are Energy Efficient Ethernet and PCIe ASPM (pcie_aspm=off on the kernel command line).