xmonadを再起動した時xkeysnailが終了してくれなくて2重起動するようになっていたのでsystemdに管理だけ任せて起動はxmonad側で行うようにしました
xmonadで起動したzshのスクリプトがxmonadの終了時に終了しない
spawn ".xmonad/xkeysnail-daemon"
としてstartupHookに差し込んであるスクリプトが終了しません.
xkeysnail-daemonの内容は以下です.
#!/usr/bin/env zsh
set -ux
while
do
sudo xkeysnail --quiet ~/.xkeysnail/config.py
>&2 echo "error: xkeysnail rebooted!"
done
xmonadを終了してもこのスクリプトが終了しないため, xmonadを再起動したら結果的にxkeysnailが2重に起動することになり, Linuxカーネルが滅茶苦茶エラーを吐くことになります.
init_uevent_argv: buffer size too small
でjournalが埋め尽くされます!
zshスクリプトって親プロセスが死んでも生き残るの?
端末でこれを実行して端末のタブを消してみたら, 見事トップレベルのプロセスになりますね…
killでシグナルを送ってやると素直に終了するのですが.
killだとちゃんと終了するので, trapコマンドについて読んでも無駄っぽいですね.
スクリプト終了イベントの捕捉と zsh の非互換性 - 拡張 POSIX シェルスクリプト Advent Calendar 2013 - ダメ出し Blog
root権限持って動いているのが差異を生み出しているような気もしなくはないですね.
この件についてはよくわからないし, 真面目に調査する方法がわかりません.
諦めてsystemdに頼ることにしました
諦めてsystemdのデーモン化することにしました. 初めからこうしていれば再起動の制御もsystemdが自動で面倒を見てくれます.
systemdのデーモンにしていれば, 少なくとも2重に起動することは無くなるはずです.
[Unit]
Description=xkeysnail
Requires=display-manager.service
After=display-manager.service
[Service]
ExecStart=/usr/bin/xkeysnail --quiet /home/ncaq/.xkeysnail/config.py
Restart=always
[Install]
WantedBy=graphical.target
ルートで起動するデーモンがホームディレクトリの設定ファイルを見ているのがとても奇妙ですが. とりあえずこれで解決しません.
ディスプレイマネージャの起動を待ってもディスプレイを認識しないので, ユーザから動かす必要があるようですね.
既にgriveで行っているのでuser版のsystemdにはそんなに抵抗がありません.
xkeysnailをsystemdでデーモン化 - Qiita
が参考になりました.
[Unit]
Description=xkeysnail
[Service]
ExecStart=/usr/bin/sudo xkeysnail --quiet /home/ncaq/.xkeysnail/config.py
ExecStop=/usr/bin/sudo kill -s QUIT $MAINPID
Restart=on-failure
RestartSec=1s
[Install]
WantedBy=graphical.target
で動くようにはなりました.
しかし一度xmonadが立ち上がる前に起動を試みていて, 立ち上がったあとの再起動で有効になるのは気になるところです. ちゃんと依存関係を参照して有効な時に立ち上がるようにしたいですね.
しかしディスプレイマネージャへの依存ならともかく, ウィンドウマネージャの依存は存在しない…
target作る方法あるらしいですが極めて面倒くさい.
disableのままユニットを配置して, xmonadのstartHook側で
spawn "systemctl --user restart xkeysnail"
手動で起動してやれば問題ありませんね.
systemdに起動を任せられなかったのは残念ですが, これで少なくとも2重起動は存在しなくなるので問題は解決です.