2009-06-11 4 views
3

J'ai un problème intéressant (au moins pour moi): je n'arrive pas à trouver un moyen fiable et transférable d'obtenir des informations sur les processus des petits-enfants dans certains cas. J'ai une application, AllTray, que j'essaie de mettre au travail dans certains cas étranges où son sous-processus engendre un enfant puis meurt. Le travail d'AllTray consiste essentiellement à ancrer une application dans la barre des tâches, qui est (généralement) spécifiée comme une ligne de commande pour AllTray à invoquer (par exemple, alltray xterm démarre xterm et le gère dans AllTray).Comment suivre de manière fiable les processus enfant/petit-enfant sur un système POSIX?

La plupart des logiciels d'interface graphique fonctionnent parfaitement. Il définit la propriété _NET_WM_PID sur sa fenêtre (ou une bibliothèque de widgets) et tout va bien, car _NET_WM_PID == fork() ed child. Cependant, dans certains cas (comme lors de l'exécution de oowriter ou d'un logiciel écrit pour s'exécuter sous KDE comme K3b), le processus enfant qu'AllTray exécute est un wrapper, que ce soit un script shell (comme dans le cas de OO.o) ou un étrange programme que fork() s et exec() lui-même et efficacement lui-même les arrière-plans, puisque le processus parent meurt très tôt. J'ai eu l'idée de ne pas récolter mes processus fils, afin de conserver dans la table de processus l'identifiant de processus parent pour mes petits-enfants, afin que je puisse les relier à moi en traversant l'arbre généalogique de bas en haut. Haut. Cela ne fonctionne pas, cependant: une fois que mon processus enfant meurt et se transforme en zombie, le système considère mon processus petit-enfant comme un orphelin, et l'adopte. Cela semble être le cas sur au moins Linux 2.6 et NetBSD; Je suppose que c'est probablement la norme, et POSIX ne semble pas le spécifier, alors j'espérais le contraire.

Puisque cette approche ne fonctionne pas, j'ai pensé à utiliser LD_PRELOAD et intercepter l'appel de mon processus fils à fork(), et de transmettre des informations à mon processus parent. Cependant, je crains que cela ne soit pas aussi portable que la solution idéale, parce que les différents systèmes ont des règles différentes sur la façon dont le linker dynamique fait des choses comme LD_PRELOAD. Cela ne fonctionnera pas pour les applications GUI setuid/setgid, sans que la bibliothèque auxiliaire ne soit aussi setuid ou setgid, au moins sur les systèmes Linux. Généralement, ça sent mauvais comme une mauvaise idée, et je me sens plutôt hackish.

Donc, je suis en espérant que quelqu'un a une idée sur la façon de le faire, ou si l'idée de se fonder sur un mécanisme comme LD_PRELOAD est vraiment la seule option que j'ai peu de noyaux rapiéçage (qui est pas aller se passer).

Répondre

1

Vous pouvez étudier la possibilité d'utiliser process groups pour suivre, bien, les groupes de processus. Un groupe de processus est une propriété (juste un nombre) que vous pouvez définir avant de forker, et les processus fils l'héritent automatiquement. AllTray peut créer un nouveau groupe de processus pour chaque application démarrée avec lui. Vous pouvez envoyer des signaux à tous les membres du groupe de processus. Je suppose que les signaux les plus utiles ici seraient TERM et KILL, afin de tuer une application gérée dans AllTray.

Je ne suis pas sûr s'il existe un moyen pratique de savoir si tous les membres du groupe de processus ont déjà quitté ou non. Vous devrez peut-être recourir à la liste complète des processus et appeler le getpgid pour chaque processus pour voir s'il en reste dans le groupe de processus.

Notez que les groupes de processus ne fonctionneront pas pour les applications qui créent elles-mêmes de nouveaux groupes de processus. Mais c'est relativement rare et vous n'avez probablement pas à vous soucier de telles applications.

+0

Hrm. Je vais jeter un coup d'oeil là-dessus, et voir ce qui se passe. L'idée semble bonne, cependant.Y a-t-il une raison pour laquelle créer un nouveau groupe de processus unique serait insuffisant? Actuellement AllTray ne gère qu'une seule application, et elle finira par gérer plus, mais si un seul pgid peut faire le travail juste pour trouver les processus dont il devrait s'occuper, ce serait suffisant, je pense. –

+0

Je peux imaginer ce défaut avec si le wrapper lance un KDE <=3 or > 4.3 via kdeinit, ou Firefox s'il a déjà d'autres fenêtres ouvertes, etc ... dans ces cas, la nouvelle fenêtre est créée par un processus dans un arbre complètement différent. – ephemient

+0

@ ephemient Je sais que les applications KDE font des choses étranges, et c'est l'un des cas que j'essaie de résoudre. Je ne peux pas faire grand-chose à propos de FF ou de gnome-terminal quand il y a déjà un processus en cours, bien que j'ai quelques idées pour essayer de le faire. Ce que les moyens utilisateur, que je pense, est possible. –

Questions connexes