web-dev-qa-db-fra.com

Pourquoi cette règle udev est-elle bloquante?

Voici une règle de mon répertoire /lib/udev/rules.d:

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

Voici le contenu simple du script udev-receiver.sh:

#!/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

Lorsque je connecte mon appareil, le résultat de external.log est celui attendu:

UDEV-RECEIVER INIT
UDEV-RECEIVER FINISH
Done

Cependant, je suis aussi en train de suivre le syslog /var/log/syslog et je constate que même si j'ai créé le processus de longue durée sleep, udev l'initialisation du périphérique se bloque après l'affichage de Done dans mon fichier external.log.

C’est important parce que j’essaie de définir certaines propriétés de l’appareil via xinput, mais celui-ci ne figure pas dans la liste via xinput list tant que l’initialisation complète de udev n’est pas terminée (après l’opération Done apparaît dans external.log).

Selon dev (7) - Page de manuel Linux

"Ajouter un programme à la liste des programmes à exécuter pour un périphérique spécifique. Cela ne peut être utilisé que pour des tâches très brèves. L'exécution d'un processus d'événement sur une longue période peut bloquer tous les autres événements de ce périphérique ou d'un périphérique dépendant. Les tâches de longue durée doivent être immédiatement détachées du processus d’événement lui-même. "

Je ne parviens pas à réconcilier la page de manuel et le comportement observé. Quelqu'un peut-il nous éclairer ou offrir un meilleur moyen de définir des propriétés via xinput lorsqu'un périphérique est inséré?

Merci!

5
Mike Knoop

Répondant à ma propre question après de nombreuses recherches supplémentaires.

La nouvelle "philosophie" d'udev

Apparemment, la nouvelle manière "appropriée" d'utiliser udev n'est pas d'engager des processus longs.

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

RUN ... Les démons de démarrage ou autres processus longs ne conviennent pas à udev; les processus forkés, qu'ils soient détachés ou non, seront automatiquement supprimés une fois le traitement des événements terminé.

Notez à quel point cela est en contradiction avec la citation de la page de manuel dans OP.

Ma meilleure hypothèse est qu'un récent changement de udev (~ 2012 parfois) force tous les processus , y compris leurs enfants forkés à se terminer avant de permettre l'exécution se poursuivant comme un mécanisme d'application de cette nouvelle philosophie.

Par conséquent, toute la documentation facilement accessible et les réponses sur le Web qui donnent le modèle dans OP en tant que solution sont maintenant brisées.

La nouvelle philosophie de configuration longue durée est compréhensible dans l'instance lorsque vous parlez d'un démon qui est toujours en cours d'exécution lorsque le périphérique est branché. Cependant, il efface le cas d'utilisation effectif defer.

Workaround

Néanmoins, j'ai aussi découvert une solution de contournement:

/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 Ceci a été testé et fonctionne sur Ubuntu 13.04

Remarque Vous devez installer at, qui est un paquet de tâches asynchrone via Sudo apt-get install at

J'ai reconstitué la solution de contournement de https://unix.stackexchange.com/questions/28548/how-to-run-custom-scripts-upon-usb-device-plug-in

3
Mike Knoop