Wie verfolgen Sie alle abzustellenden Prozesse zur Bereinigung?

8

Ich habe ein Programm, das fork() und exec() mehrere Prozesse in einer Kette haben kann. Zum Beispiel: Prozess A - & gt; Gabel, Exec B - & gt; Gabel, Exec C - & gt; Gabel, Exec D. So A ist die Ur-Urgroßeltern von C.

Jetzt ist das Problem, dass ich keine Kontrolle über die Prozesse B, C und D habe. Es können also mehrere Dinge passieren.

  1. Es kann vorkommen, dass ein absteigender Prozess setsid() ausführen kann, um seine Prozessgruppe und Sitzung zu ändern.
  2. Oder einer der absteigenden Prozesse stirbt (zB C) und daher wird sein Kind (D) von init.
  3. parented

Daher kann ich mich nicht auf die Prozessgruppen-ID oder Eltern-ID verlassen, um alle Nachkommen von A zu verfolgen. Gibt es eine zuverlässige Möglichkeit, alle Nachkommen zu verfolgen? Genauer gesagt möchte ich alle Nachkommen töten (Waisen und andere).

Es wäre auch großartig, wenn es POSIX-konform ist.

    
vinodkone 04.08.2011, 06:20
quelle

2 Antworten

2

Ich stimme caf Allgemeine Stimmung: Wenn ein Prozess setsid aufruft, heißt es, dass er alleine leben will, egal was passiert. Sie müssen sorgfältig überlegen, ob Sie sie wirklich töten wollen.

Manchmal wird eine bestimmte "Super-Session" einen Prozessbaum enthalten. Es gibt kein Tool, das solche Super-Sessions in der POSIX-Toolbox bietet, aber ich werde ein paar Lösungen vorschlagen. Jede Lösung hat ihre eigenen Grenzen, daher ist es wahrscheinlich, dass sie nicht alle auf Ihren Fall anwendbar sind, aber hoffentlich wird eine davon geeignet sein.

Eine saubere Lösung besteht darin, die Prozesse in ihrer eigenen virtualisierten Umgebung auszuführen. Dies könnte ein FreeJSD-style sein, Linux Cgroups oder jede andere Art von Virtualisierungstechnologie. Die Einschränkungen dieses Ansatzes bestehen darin, dass Virtualisierungstechnologien vom Betriebssystem abhängig sind und die Prozesse in einem etwas anderen Kontext ablaufen.

Wenn Sie nur eine einzige Instanz dieser Prozesse auf dem System haben und Sie können root involvieren, führen Sie die Prozesse als dedizierter Benutzer aus. Die Super-Sitzung ist definiert als die Prozesse, die als dedizierter Benutzer ausgeführt werden. Töte die Nachkommen mit kill(-1, signum) (beachte, dass dies den Killer-Prozess selbst auslöst, wenn er nicht blockiert oder das Signal behandelt wird).

Sie können den Prozess veranlassen, eine eindeutige Datei zu öffnen, indem Sie sicherstellen, dass das Flag FD_CLOEXEC für den Dateideskriptor gesetzt ist. Alle untergeordneten Prozesse erben die geöffnete Datei dann, wenn sie das Flag FD_CLOEXEC vor dem Aufruf von execve explizit entfernen oder die Datei schließen. Töte die Prozesse mit fuser -k oder indem du die Liste der Prozess-IDs mit fuser oder lsof erhältst ( fuser ist in POSIX, aber nicht fuser -k ). Beachten Sie, dass es eine Race-Bedingung gibt: Ein Prozess kann zwischen die Zeit, die Sie fuser aufrufen und die Zeit, die Sie es töten; Daher müssen Sie fuser in einer Schleife aufrufen, bis keine Prozesse mehr auftreten (führen Sie keine Schleife durch, bis alle Prozesse tot sind, da dies eine Endlosschleife sein könnte, wenn einer der Prozesse Ihr Signal blockiert).

Sie können eine eindeutige zufällige Zeichenfolge generieren und eine Umgebungsvariable mit diesem Namen oder einem bekannten Namen und dieser eindeutigen Zeichenfolge als Wert definieren. Es wird von allen untergeordneten Prozessen übernommen, sofern sie nicht ihre Umgebung ändern. Es gibt keine Möglichkeit, nach Prozessen zu suchen, die auf ihrer Umgebung basieren oder sogar die Umgebung eines anderen Prozesses zu erhalten. Bei vielen Unix-Varianten können Sie die Informationen mit der Option ps erhalten (z. B. ps -e auf * BSD oder ps e auf Linux); Die Information ist möglicherweise nicht leicht zu analysieren, aber das Vorhandensein der eindeutigen Zeichenkette ist ein ausreichender Indikator. Wie bei fuser oben, notieren Sie die Notwendigkeit einer Schleife, um eine Race-Bedingung zu vermeiden, wenn ein Nachkomme fork zu spät aufruft, um sein Kind zu bemerken, aber bevor Sie das Elter töten können.

Sie können LD_PRELOAD eine kleine Bibliothek erstellen, die einen Thread abzweigt, der auf einem Kommunikationskanal horcht, und dessen Prozess bei der Benachrichtigung beendet. Dies kann den Prozess stören, wenn es von all seinen eigenen Threads weiß; Es ist nur eine Möglichkeit auf Architekturen, bei denen die Standardbibliothek immer Thread-sicher ist und Sie statisch verknüpfte Prozesse vermissen werden. Der Kommunikationskanal kann alles sein, was dem Master-Prozess ermöglicht, den Selbstmordbefehl zu senden; Eine Möglichkeit ist eine Pipe, bei der jeder absteigende Prozess eine blockierende Leseoperation ausführt und der Vorgängerprozess die Pipe schließt, um die Nachkommen zu benachrichtigen. Übergeben Sie die Datei-Deskriptor-Nummer über eine Umgebungsvariable.

    
Gilles 04.08.2011, 12:39
quelle
4

Der POSIX-Weg dazu besteht einfach darin, Prozessgruppen zu verwenden. Abgeleitete Prozesse, die ihre Prozessgruppe / Sitzung explizit ändern, treffen eine bewusste Entscheidung, dass ihre Lebensdauer nicht von ihrem ursprünglichen Elternteil verfolgt wird - sie emanzipieren sich spezifisch von der Kontrolle der Eltern. Solche Prozesse sind keine Waisen - sie sind Erwachsene, die "das Nest geflogen" haben und die Kontrolle über ihr eigenes Leben ausüben wollen.

    
caf 04.08.2011 07:09
quelle