You are not logged in.

#1 2022-04-26 14:55:56

Equiphract
Member
Registered: 2021-05-04
Posts: 11

Weird stuff happens after trying to create monitor hotplug udev rule

I tried to create a udev rule to detect when external monitors get connected. At first it seemed to work with the configuration I've given below. When I unplugged my external monitor from DP-1, it disabled DP-1 with xrandr, when I replugged my monitor it enabled it again with the given xrandr command. But then my system suddenly started acting up and I could not tell you why. Now when I unplug und replug my monitor my X-Server crashed, even after having rebooted multiple times. Another weird thing is that I now have to mouse cursors on my screen... one is static and the one I can control with my mouse is flickering. I must say this a very frustrating experience... this should really not be that hard...

/etc/udev/rules.d/70-monitor.rules:

ACTION=="change", SUBSYSTEM=="drm", KERNEL=="card0", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/me/.Xauthority", RUN+="/bin/sh /home/me/Executables/monitor_hotplug.sh &"

/home/me/Executables/monitor_hotplug.sh:

#!/bin/sh

# Get out of town if something errors
set -e

HDMI_STATUS=$(</sys/class/drm/card0/card0-HDMI-A-1/status )
DP_STATUS=$(</sys/class/drm/card0/card0-DP-1/status )

# The following is needed, otherwise xrandr executions have no effect... don't
# ask me why, all I know is that this wasted 3 hours of my life. I hate
# computers.
/usr/bin/xrandr -v

if [ "connected" == "$HDMI_STATUS" ]; then
  /usr/bin/xrandr --output HDMI-1 --same-as eDP-1 --auto --mode 1920x1080
else
  /usr/bin/xrandr --output HDMI-1 --off
fi

if [ "connected" == "$DP_STATUS" ]; then
  /usr/bin/xrandr --output DP-1 --left-of eDP-1 --auto
else
  /usr/bin/xrandr --output DP-1 --off
fi

Edit 2022-04-26-18-11-00:
I just realised that the

+=

operator in

RUN+="/bin/sh /home/me/Executables/monitor_hotplug.sh &"

is unnecessary and could potentially lead to faulty behaviour, so I changed the udev rule to the following (after rebooting):

/etc/udev/rules.d/70-monitor.rules:

ACTION=="change", SUBSYSTEM=="drm", KERNEL=="card0", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/me/.Xauthority", RUN="/bin/sh /home/me/Executables/monitor_hotplug.sh &"

This change seemed to fix my issues: When I unplug my external monitor

/usr/bin/xrandr --output DP-1 --off

gets executed and when I attach it again 

/usr/bin/xrandr --output DP-1 --left-of eDP-1 --auto

gets executed. Does anyone have a clue as to why I experienced the buggy behaviour described above? Also, does anyone happen to know what the deal is with having to include the line

/usr/bin/xrandr -v

in order for subsequent xrandr calls to work?

Edit 2022-04-27-14-01-00:
Nope, not fixed, double cursor randomly appeared again when no external monitor was attached.

Last edited by Equiphract (2022-04-27 12:01:03)

Offline

#2 2022-04-27 07:13:11

dimich
Member
From: Kharkiv, Ukraine
Registered: 2009-11-03
Posts: 83

Re: Weird stuff happens after trying to create monitor hotplug udev rule

man 7 udev:

Starting daemons or other long-running processes is not allowed; the forked processes, detached or not, will be unconditionally killed after the event handling has finished. In order to activate long-running processes from udev rules, provide a service unit and pull it in from a udev device using the SYSTEMD_WANTS device property. See systemd.device(5) for details.

Offline

#3 2022-04-27 10:13:27

Equiphract
Member
Registered: 2021-05-04
Posts: 11

Re: Weird stuff happens after trying to create monitor hotplug udev rule

dimich wrote:

man 7 udev:

Starting daemons or other long-running processes is not allowed; the forked processes, detached or not, will be unconditionally killed after the event handling has finished. In order to activate long-running processes from udev rules, provide a service unit and pull it in from a udev device using the SYSTEMD_WANTS device property. See systemd.device(5) for details.

How does my script qualifiy as a long-running process?

Running

time /home/me/Executables/monitor_hotplug.sh

prints the following output to the terminal:

real    0m0.228s
user    0m0.023s
sys     0m0.022s

That does not seem very long-running to me (or is it? I am no expert at Linux, yet tongue)

Offline

#4 2022-04-27 15:22:12

dimich
Member
From: Kharkiv, Ukraine
Registered: 2009-11-03
Posts: 83

Re: Weird stuff happens after trying to create monitor hotplug udev rule

Equiphract wrote:

How does my script qualifiy as a long-running process?

You attempt to run background script. As parent shell exit, all child processes would be killed. Script process may be killed at any execution point.
But in your case it won't go to background anyway. Ampersand is just a second argument to /bin/sh, not a part of a shell command.
That's first what i can see.
You can set executable flag to script and call it directly without /bin/sh. Then i'd set some debug logging in the script and see what's happening there.

Last edited by dimich (2022-04-27 15:23:30)

Offline

#5 2022-04-27 15:47:15

V1del
Forum Moderator
Registered: 2012-10-16
Posts: 16,186

Re: Weird stuff happens after trying to create monitor hotplug udev rule

I'd also say the backgrounding immediately kills your script, drop the ampersand from the RUN line

Online

#6 2022-04-27 22:19:27

Equiphract
Member
Registered: 2021-05-04
Posts: 11

Re: Weird stuff happens after trying to create monitor hotplug udev rule

Ok so I changed my /home/me/Executables/monitor_hotplug.sh to the following:

#!/bin/sh

LOGFILE="/tmp/udev_hotplug.log"

echo >> "$LOGFILE"
date >> "$LOGFILE"

HDMI_STATUS=$(cat /sys/class/drm/card0/card0-HDMI-A-1/status)
DP_STATUS=$(cat /sys/class/drm/card0/card0-DP-1/status)

# The following is needed, otherwise xrandr executions have no effect... don't
# ask me why, all I know is that this wasted 3 hours of my life. I hate
# computers.
/usr/bin/xrandr -v

if [ "connected" = "$HDMI_STATUS" ]; then
  echo "HDMI connected" >> "$LOGFILE"
  /usr/bin/xrandr -v --output HDMI-1 --same-as eDP-1 --auto --mode 1920x1080 >> $LOGFILE 2>&1
  echo "xrandr should have activated HDMI" >> "$LOGFILE"
else
  echo "HDMI not connected" >> "$LOGFILE"
  /usr/bin/xrandr -v --output HDMI-1 --off >> $LOGFILE 2>&1
  echo "xrandr should have deactivated HDMI" >> "$LOGFILE"
fi

if [ "connected" = "$DP_STATUS" ]; then
  echo "DP connected" >> "$LOGFILE"
  /usr/bin/xrandr -v --output DP-1 --left-of eDP-1 --auto >> $LOGFILE 2>&1
  echo "xrandr should have activated DP" >> "$LOGFILE"
else
  echo "DP not connected" >> "$LOGFILE"
  /usr/bin/xrandr -v --output DP-1 --off >> $LOGFILE 2>&1
  echo "xrandr should have deactivated DP" >> "$LOGFILE"
fi

And, for now at least, it seems to work flawlessly... I don't know if removing the "&" from the RUN key fixed it as, if I understand dimich correctly, it shouldn't have had any effect on execution anyways.

This is the content of the log file at /tmp/udev_hotplug.log after unplugging and replugging DP-1:

Thu Apr 28 00:09:37 CEST 2022
HDMI not connected
xrandr program version       1.5.1
xrandr should have deactivated HDMI
DP not connected
xrandr program version       1.5.1
xrandr should have deactivated DP

Thu Apr 28 00:09:54 CEST 2022
HDMI not connected
xrandr program version       1.5.1
xrandr should have deactivated HDMI
DP connected
xrandr program version       1.5.1
xrandr should have activated DP

Edit 2022-04-28-00-27-00:
What I still don't understand is why I need to run

/usr/bin/xrandr -v

once before the if blocks... When I comment it out and unplug my monitor it executes the script the xrandr call seems to work but plugging it in again has no effect, the external monitor stays black and I can't move my mouse cursor off screen. The funny thing is, the script seems to get executed fully, as the logs show, but xrandr itself has no effect:

Thu Apr 28 00:22:00 CEST 2022
HDMI not connected
xrandr program version       1.5.1
xrandr should have deactivated HDMI
DP not connected
xrandr program version       1.5.1
xrandr should have deactivated DP

Thu Apr 28 00:22:09 CEST 2022
HDMI not connected
xrandr program version       1.5.1
xrandr should have deactivated HDMI
DP connected
xrandr program version       1.5.1
xrandr should have activated DP

Last edited by Equiphract (2022-04-27 22:27:24)

Offline

#7 2022-04-28 06:13:44

dimich
Member
From: Kharkiv, Ukraine
Registered: 2009-11-03
Posts: 83

Re: Weird stuff happens after trying to create monitor hotplug udev rule

We don't know how synchronous are interactions between driver, sysfs, udev and xorg. Race conditions are possible. `xrandr -v` queries version from server, perhaps it makes a kind of synchronization as a side effect.

Last edited by dimich (2022-04-28 06:15:51)

Offline

#8 2022-04-28 07:52:34

Raynman
Member
Registered: 2011-10-22
Posts: 1,417

Re: Weird stuff happens after trying to create monitor hotplug udev rule

Or it simply helps by introducing a small delay? You could try `sleep 1` instead of `xrandr -v`. And you could write `xrandr` output to the log file before the `xrandr -v` to see if the newly connected status is not yet visible to xorg at that time.

I never like these hacky solutions, calling user scripts with a hardcoded username and DISPLAY from root-managed files. A race condition on top might provide an incentive to look for a cleaner alternative. I found x-on-resize the other day, but haven't actually tried it yet.

Offline

#9 2022-05-01 12:24:37

Equiphract
Member
Registered: 2021-05-04
Posts: 11

Re: Weird stuff happens after trying to create monitor hotplug udev rule

The reason why I tried doing it with udev was this entry in the wiki: https://wiki.archlinux.org/title/Udev#E … _unplugged. But I think I'll look for a different solution, maybe I can do something with systemd.

Offline

Board footer

Powered by FluxBB