Linux : résoudre le problème de double mise en veille

J’ai récemment mis à jour mon système Salix OS de la version 14.1 vers la version 14.2. Il s’agit de la troisième mise à jour que je fais et cela se passe toujours sans gros problème, si ce n’est que je dois, à chaque fois, renouveler la procédure d’installation du pilote pour le Wifi.

Cependant, il arrive de temps en temps des petites surprises, en particulier avec la gestion des boutons liés à l’énergie.

Il y d’abord la fermeture de l’écran de mon ordinateur portable pour laquelle je souhaite qu’une hibernation (appelée aussi « mise en veille prolongée » dans Microsoft Windows, ou suspend-to-disk) soit effectuée.

Et il y a ensuite la mise en veille (appelée aussi suspend-to-ram) que je souhaite déclencher lors de l’appui de la touche Lune de mon ordinateur (Fn + F1).

Pour faire tout cela, sous Slackware (pour rappel, Salix OS utilise Slackware comme base), cela se passe dans le fichier de script shell /etc/acpi/acpi_handler.sh :
#!/bin/sh
# Default acpi script that takes an entry for all actions

IFS=${IFS}/
set $@

case « $1″ in
  button)
    case « $2″ in
      power) /sbin/init 0
         ;;
      *) logger « ACPI action $2 is not defined »
         ;;
    esac
    ;;
  *)
    logger « ACPI group $1 / action $2 is not defined »
    ;;
esac

Pour déclencher l’hibernation, j’avais simplement ajouté la branche suivante dans le case :
     lid) pm-hibernate
         ;;

« lid » (qui veut dire en anglais « couvercle ») correspond au bouton (plutôt virtuel dans le cas mon ordinateur) lié à la manipulation de l’écran d’un ordinateur portable. Je l’ai donc associé à la commande pm-hibernate, qui s’occupe de mettre l’ordinateur dans l’état d’hibernation de manière correcte.

Et pour déclencher une mise en veille, j’avais simplement ajouté la branche suivante :
     sleep) pm-suspend
         ;;

« sleep » correspond à la touche Lune de mon ordinateur. Je l’ai donc associé à la commande pm-suspend, qui s’occupe de mettre l’ordinateur dans l’état de veille.

Tout cela fonctionnait plutôt bien jusqu’à une première mise à jour, suite à laquelle il est apparu que le retour d’hibernation déclenchait automatiquement une nouvelle hibernation.

L’astuce que j’avais trouvée à l’époque était d’appliquer un contrôle sur l’état effectif du bouton lid :
     lid) grep -q closed /proc/acpi/button/lid/*/state && pm-hibernate

Suite à ma récente mise à jour vers Salix OS 14.2, un problème similaire est apparu avec la mise en veille déclenchée par la touche Lune. Suite au retour de veille, une deuxième mise en veille était effectuée immédiatement.

Lors de ma recherche d’une solution sur le Web, j’ai découvert, via cet article, l’existence de l’outil acpi_listen. Cet outil permet de voir les événements ACPI exacts déclenchés. Il suffit de le lancer puis de déclencher les boutons/touches :
# acpi_listen
button/lid LID close
button/lid LID open
button/sleep SBTN 00000080 00000000
button/sleep PNP0C0E:00 00000080 00000008

Ici, le résultat montre que la fermeture et l’ouverture de l’écran déclenchent deux événements. Il montre aussi que l’appui de la touche Lune déclenche deux événements.

Il m’est donc apparu clairement qu’utiliser les deux premiers composants de l’événement ACPI ($1 et $2 dans le fichier acpi_handler.sh) n’était pas suffisant. J’ai donc adapté le script de la façon suivante :
      lid) test $4 = « close » && pm-hibernate
         ;;
      sleep) test $3 = « SBTN » && pm-suspend
         ;;

Cela a réglé le problème… jusqu’à la prochaine mise à jour en tout cas. Car les composants supplémentaires ($3 et $4 dans le script) sont-ils suffisamment stables pour être utilisés ? Qui me dit que leurs valeurs ne changera pas lors d’une prochaine mise à jour ? L’avenir nous le dira…

Ci-dessous, le script complet du fichier /etc/acpi/acpi_handler.sh, après modification :
#!/bin/sh
# Default acpi script that takes an entry for all actions

IFS=${IFS}/
set $@

case « $1″ in
  button)
    case « $2″ in
      power) /sbin/init 0
         ;;
      lid) test $4 = « close » && pm-hibernate
         ;;
      sleep) test $3 = « SBTN » && pm-suspend
         ;;
      *) logger « ACPI action $2 is not defined »
         ;;
    esac
    ;;
  *)
    logger « ACPI group $1 / action $2 is not defined »
    ;;
esac

Vus : 619
Publié par Julien L : 29