Comment créer une window X qui ne se fermera pas d'une manière autre qu'une command de terminal

J'essaie de créer un process qui commencera avec X11, sera graphique et inutilisable par mon propre user.

Plus précisément, j'ai un terminal déroulant urxvt commençant au démarrage et exécutant une session tmux tout de suite. Ce qui m'énerve, c'est que je le tue parfois avec Alt + F4 quand j'oublie que c'est le terminal déroulant et je suis censé le cacher à la place.

Bien sûr, je ne perds pas ma session tmux puisque je peux la rattacher à un autre terminal, mais je devrai relancer le terminal déroulant (avec la configuration exacte) et le rattacher et c'est fastidieux.

Ce que je voudrais faire, c'est de ne pas être en mesure d' Alt + F4 tuer ce process spécifique .

Après avoir lu ceci: rendre un process inexploitable sur Linux

J'ai compris que je devrais lancer le process comme appartenant à un autre user, mais même si je réussis à le faire dans mon propre server X avec:

sudo xhost +local: sudo runuser -l my-secondary-user -c urxvt 

Je fais face à deux comportements indésirables:

  1. Le process peut être tué par mon user principal (celui qui possède la session X)
  2. Le terminal virtuel commence à se connecter en tant que mon user secondaire (bien sûr)

Le (2) peut être rectifiable – il suffit d'exécuter une command pour se connecter en tant que mon user principal à la place – mais je n'ai aucune idée sur la façon de réparer le (1).

Y a-t-il moyen de faire ce travail, ou une autre façon de faire ce que je veux? Je préfère éviter d'avoir à créer des modules du kernel si possible.

Exécuter Arch Linux avec Openbox.

MODIFIER

J'ai pensé que je pourrais faire en sorte que Alt + F4 ne fonctionne pas pour cette window spécifique. trouvé ceci: Openbox: désactiver Alt-F4 sur une base d'application

et modifié mon rc.xml ainsi:

 <keybind key="A-F4"> <action name="If"> <application class="URxvt" title="tmux-session"> </application> <then><!-- Do nothing for urxvt-tmux-session --></then> <else> <action name="Close" /> </else> </action> </keybind> 

Cela fonctionne un peu mieux qu'avant: je ne peux pas Alt + F4 ce terminal, mais je ne peux pas non plus Alt + F4 n'importe quelle window urxvt maintenant (devinez parce que les nouvelles windows urxvt sont toutes exécutées sous le même nom de class?)

En plus de cela, je peux tuer tout ce dont j'ai besoin dans la barre de menu, ou bien cliquer avec le button droit de la souris sur mon panneau de teinte, ou, bien sûr, par command. Mais cette approche signifie que:

  1. Je peux toujours tuer mon terminal déroulant en cliquant droit dans le panneau teinte2 (peut-être réparable si je fais que le terminal déroulant n'apparaisse pas comme une icône dans le panneau – devrait être possible avec quelques searchs)
  2. Je ne peux pas Alt + F4 autres windows du terminal (ne pas aimer beaucoup, mais peut-être acceptable)

Des idées?

SOLUTION

J'ai trouvé une solution qui fonctionne pour moi en me basant sur la réponse de Dmitry et mes modifications ci-dessus:

1) je fixe un titre personnalisé à mon urxvt:

urxvt -title urxvt-drop-down

Je n'ai pas utilisé un nom personnalisé parce qu'il semble que le

urxvt -name urxvt-drop-down

command ignore le file .Xresources que j'utilise actuellement, tandis que -title l'utilise.

2) J'ai fait la touche Alt + F4 pour ignorer les terminaux intitulés urxvt-drop-down. rc.xml:

<keybind key="A-F4"> <action name="If"> <title>urxvt-drop-down</title> <then><!-- Do nothing for urxvt-drop-down --></then> <else> <action name="Close" /> </else> </action> </keybind>

3) J'ai fait que le coupable n'apparaisse jamais dans la barre des tâches, et puisque la barre skip_taskbar décompose également la window, la recentre. rc.xml:

<application title="urxvt-drop-down"> <skip_taskbar>yes</skip_taskbar> <focus>yes</focus> </application>

Même si cela résout le problème pour moi, c'est essentiellement une solution de contournement. Je ne suis donc pas encore sûr que la réponse de Stéphane soit la bonne pour cette question.

Besoin de faire un peu de search sur les commands présentées pour comprendre ce qui se fait.

Je n'utiliserai cependant pas xterm, car je veux une transparence et une capacité de drop-down (une sorte de drop-down pourrait être possible avec xterm aussi je pense, mais la transparence n'est certainement pas sans un compositeur – et j'ai gagné ' t utiliser un compositeur)

Si le passage à xterm est une option, vous pouvez utiliser le hack ci-dessous. Il y a cependant quelques mises en garde. Une fois que vous répondez à la plupart d'entre eux, la solution finit par se compliquer, voir le script final à la fin.

 xterm -e 'trap "" HUP; your-application' 

A la réception de l'instruction de fermeture du gestionnaire de windows, xterm enverra un SIGHUP au groupe de process de votre application et ne se quittera que lorsque le process sera rétabli.

Cela suppose que votre application ne réinitialise pas le gestionnaire pour SIGHUP et pourrait avoir des effets secondaires indésirables pour les enfants de votre application.

Les deux semblent être un problème si votre application est tmux .

Pour contourner ceux-ci, vous pourriez faire:

 xterm -e sh -c 'bash -mc tmux <&1 & trap "" HUP; wait' 

De cette façon, tmux serait lancé dans un groupe de process différent, de sorte que seul le sh recevrait le SIGHUP (et l'ignorer).

Cela ne s'applique pas à tmux qui réinitialise le gestionnaire pour ces signaux, mais dans le cas général, en fonction de votre implémentation de sh , les signaux SIGINT, SIGQUIT et généralement les deux seront ignorés pour votre application car ce bash est démarré comme une command asynchronous à partir d'un sh non-interactif. Cela signifie que vous ne pouvez pas interrompre votre application avec Ctrl + C ou Ctrl + \ .

C'est une exigence POSIX. Certains shells comme mksh ne l'honorent pas (du less pas les versions actuelles), ou seulement en partie comme dash qui le fait pour SIGINT mais pas SIGQUIT. Donc, si mksh est disponible, vous pourriez faire:

 xterm -e mksh -c 'bash -mc your-application <&1 & trap "" HUP; wait' 

(bien que cela puisse ne pas fonctionner dans les futures versions de mksh s'ils décident de corriger cette non-conformité).

Ou si vous ne pouvez pas garantir que mksh ou bash sera disponible ou préférez ne pas countr sur un comportement qui pourrait changer à l'avenir, vous pouvez faire leur travail à la main avec perl et par exemple écrire un script wrapper unclosable-xterm comme:

 #! /bin/sh - [ "$#" -gt 0 ] || set -- "${SHELL:-/bin/sh}" exec xterm -e perl -MPOSIX -e ' $pid = fork; if ($pid == 0) { setpgrp or die "setpgrp: $!"; tcsetpgrp(0,getpid) or die "tcsetpgrp: $!"; exec @ARGV; die "exec: $!"; } die "fork: $!" if $pid < 0; $SIG{HUP} = "IGNORE"; waitpid(-1,WUNTRACED)' "$@" 

(pour être appelé unclosable-xterm your-application and its args ).

Un autre effet secondaire est que ce nouveau groupe de process que nous créons et mettons en avant-plan (avec bash -m ou setpgrp + tcsetpgrp ci-dessus) n'est plus le groupe de process leader de session, donc plus un groupe de process orphelins soi-disant soigné maintenant ( sh ou perl )).

Cela signifie que lorsque vous appuyez sur Ctrl + Z , ce process sera suspendu. Ici, notre parent insouciant va juste quitter, ce qui signifie que le groupe de process obtiendra un SIGHUP (et j'espère mourir).

Pour éviter cela, nous pourrions simplement ignorer le SIGTSTP dans le process enfant, mais si votre application est un shell interactif, Ctrl-Z ne fonctionnera pas pour les tâches exécutées pour certaines implémentations comme mksh , yash ou rc .

Ou nous pourrions mettre en place un parent plus prudent qui reprend l'enfant chaque fois qu'il est arrêté, comme:

 #! /bin/sh - [ "$#" -gt 0 ] || set -- "${SHELL:-/bin/sh}" exec xterm -e perl -MPOSIX -e ' $pid = fork; if ($pid == 0) { setpgrp or die "setpgrp: $!"; tcsetpgrp(0,getpid) or die "tcsetpgrp: $!"; exec @ARGV; die "exec: $!"; } die "fork: $!" if $pid < 0; $SIG{HUP} = "IGNORE"; while (waitpid(-1,WUNTRACED) > 0 && WIFSTOPPED(${^CHILD_ERROR_NATIVE})) { kill "CONT", -$pid; }' "$@" 

Un autre problème est que si xterm disparu pour une autre raison que la fermeture du gestionnaire de windows, par exemple si xterm est tué ou perd la connection au server X (à cause de xkill , l'action de destruction de votre gestionnaire de windows ou du server X crashes par exemple), alors ces process ne mourront pas car SIGHUP serait également utilisé dans ces cas pour les terminer. Pour contourner cela, vous pouvez utiliser poll() sur le terminal (qui serait démoli quand xterm va):

 #! /bin/sh - [ "$#" -gt 0 ] || set -- "${SHELL:-/bin/sh}" exec xterm -e perl -w -MPOSIX -MIO::Poll -e ' $pid = fork; # start the command in a child process if ($pid == 0) { setpgrp or die "setpgrp: $!"; # new process group tcsetpgrp(0,getpid) or die "tcsetpgrp: $!"; # in foreground exec @ARGV; die "exec: $!"; } die "fork: $!" if $pid < 0; $SIG{HUP} = "IGNORE"; # ignore SIGHUP in the parent $SIG{CHLD} = sub { if (waitpid(-1,WUNTRACED) == $pid) { if (WIFSTOPPED(${^CHILD_ERROR_NATIVE})) { # resume the process when stopped # we may want to do that only for SIGTSTP though kill "CONT", -$pid; } else { # exit when the process dies exit; } } }; # watch for terminal hang-up $p = IO::Poll->new; $p->mask(STDIN, POLLERR); while ($p->poll <= 0 || $p->events(STDIN) & POLLHUP == 0) {}; kill "HUP", -$pid; ' "$@" 

Votre question a un titre quelque peu trompeur, menant votre search dans la mauvaise direction. Lorsque vous fermez une window dans X , le server ne tue pas votre process . Au lieu de cela, il envoie un message WM_DELETE_WINDOW au process, qui à son tour se termine. Ce fait condamne votre première approche: même si vous définissez le drapeau SIGNAL_UNKILLABLE , vous pourrez toujours le fermer.

Votre deuxième approche semble utilisable, tout ce que vous avez à faire est de discriminer une window de terminal unique contre tous les autres. Une façon d'y parvenir est de lancer urxvt avec un titre particulier, par exemple urxvt -name urxvt-iddqd , et créer une règle pour son nom:

 <keybind key="A-F4"> <action name="If"> <application title="urxvt-iddqd" title="tmux-session"> </application> <then><!-- Do nothing for urxvt-tmux-session --></then> <else> <action name="Close" /> </else> </action> </keybind>