6

Here is a rule from my /lib/udev/rules.d directory:

SUBSYSTEM=="input", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="008c", RUN+="/home/mikeknoop/scripts/udev-receiver.sh"

Here is the simple contents of the udev-receiver.sh script:

#!/bin/bash

echo "UDEV-RECEIVER INIT" >> /var/log/external.log

{
sleep 5;
echo "Done" >> /var/log/external.log
} &

echo "UDEV-RECEIVER FINISH" >> /var/log/external.log

When I plug in my device, the output of external.log is as you would expect:

UDEV-RECEIVER INIT
UDEV-RECEIVER FINISH
Done

However, I am also tailing the syslog /var/log/syslog and can see that even though I have forked the long-running sleep process, udev device initialization is blocking until after Done shows up in my external.log file.

The reason this is important is because I am trying to set some device properties via xinput but the device isn't listed via xinput list until the entire udev initialization is completed (until after Done shows up in external.log).

According to the udev(7) - Linux man page

"Add a program to the list of programs to be executed for a specific device. This can only be used for very short running tasks. Running an event process for a long period of time may block all further events for this or a dependent device. Long running tasks need to be immediately detached from the event process itself."

I am unable to reconcile the man page and the behavior that I am seeing. Can anyone shed light or offer a better way to set properties via xinput when a device is inserted?

Thanks!

1 Answer 1

3

Answering my own question after lots of further research.

The new udev "philosophy"

Apparently the new "proper" way to use udev is not to incur long-running processes.

Via http://blog.fraggod.net/2012/06/16/proper-ish-way-to-start-long-running-systemd-service-on-udev-event-device-hotplug.html:

RUN ... Starting daemons or other long running processes is not appropriate for udev; the forked processes, detached or not, will be unconditionally killed after the event handling has finished.

Note how this is in contradiction to the man-page citation in OP.

My best guess is a recent udev change (~2012 sometime) forces all processes including their forked children to finish before allowing execution to continue as an enforcement mechanism for this new philosophy.

Therefore, all easily accessible documentation and answers on the web which give the pattern in OP as a solution are now broken.

The new long-running pattern philosophy is understandable in the instance when you're talking about some daemon that is always running when the device is plugged in. However, is obliterates the effective defer use-case along with it.

Workaround

Nonetheless, I also discovered a workaround:

/lib/udev/rules.d/98-mouse-config.rules/

SUBSYSTEM=="usb", ATTRS{idVendor}=="045e", ATTRS{idProduct}=="008c", ACTION=="add|remove", ENV{ID_TYPE}!="hid", RUN+="/home/mikeknoop/scripts/udev-receiver.sh"

udev-receiver.sh

#!/bin/bash
echo /home/mikeknoop/scripts/mouse.sh | at now

mouse.sh

#!/bin/bash
sleep 3;
export DISPLAY=":0.0"
export XAUTHORITY="/home/mikeknoop/.Xauthority"
/usr/bin/xinput --set-prop 'pointer:Microsoft Microsoft Wireless Optical Mouse® 1.0A' 'Device Accel Constant Deceleration' 2.00000
... more xinput rules here

Note This was tested and works on Ubuntu 13.04

Note You'll need to install at which is an async task package via sudo apt-get install at

I pieced together the workaround from https://unix.stackexchange.com/questions/28548/how-to-run-custom-scripts-upon-usb-device-plug-in

1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .