SIGCHLD wird nicht für Prozesse empfangen, die mit sudo ausgeführt werden

  • Ich bin gerade dabei, eine Shell zu schreiben. Ich führe Prozesse aus und verwende einen SIGCHLD Signal-Handler, um sie zu bereinigen (warten), wenn sie abgeschlossen sind.

    Alles hat funktioniert - außer wenn ich Prozesse mit Eskalation ausführe Privilegien mit sudo. In diesen Fällen erhalte ich nie ein SIGCHLD -Signal - daher weiß ich nie, dass die Ausführung des Vorgangs abgeschlossen ist.

    Wenn ich einen Befehl wie sudo ls erhalte, bekomme ich Führen Sie das Programm sudo aus und geben Sie ls als Parameter an. Ich führe diese Ausführung mit execvp aus.

    Wenn ich nach der Ausführung von sudo ls auf ps -aux sehe, sehe ich Folgendes:

     root      4795  0.0  0.0   4496  1160 pts/29   S+   16:51   0:00 sudo ls
    root      4796  0.0  0.0      0     0 pts/29   Z+   16:51   0:00 [ls] <defunct>
     

    Also lief sudo und erhielt pid = 4795 zugewiesen, wobei dem Kind (ls) 4796 zugewiesen wurde. Das Kind hat seine Aufgabe erfüllt und sitzt jetzt in einem Zombie-Zustand. sudo scheint den Zombie-Prozess nicht ernten zu wollen und sitzt einfach dort.

    Ich würde gerne wissen, was dieses Verhalten verursacht - ich habe verschiedene Techniken ausprobiert Um diese Zombie-Prozesse zu bereinigen, z. B. das Ausführen meiner Shell unter sudo und das direkte Warten auf sudo und das PID, das sudo ausführt (4796 im obigen Beispiel). Keine dieser Techniken hat funktioniert.

    Wie immer wird jeder Hinweis geschätzt.

    22 November 2011
    BSchlinker
1 answer
  • Mein erster Gedanke ist eine fehlerhafte Signalverarbeitung, aber in Ihrem Beitrag sind nicht genügend Informationen vorhanden, um Testcode zu schreiben, um Ihren Fehler zu replizieren. Aber ich kann Ihnen einige Orte geben, an denen Sie suchen können. Verzeihen Sie mir, wenn ich ein paar Signalgrundlagen bespreche, die Sie für zukünftige Leser bereits kennen.

    Zunächst weiß ich nicht, ob Sie das Altsignal verwenden () oder die neue POSIX sigaction () - Signalroutine zum Abfangen von Signalen. sigset () ist ein nützliches Dazwischen von GNU.

    Legacy-Signale - signal ()
    Es ist nahezu unmöglich, wenn nicht unmöglich, in allen Umgebungen einen luftdichten Signalprozessor zu verwenden, der den ursprünglichen Signalprozessor verwendet.

    • Ein Einige UNIX-Systeme, die den Signalhandler betreten, können den Handler auf den Standardzustand zurücksetzen. Nachfolgende Signale gehen garantiert verloren, es sei denn, der Handler setzt das Signal explizit zurück.
    • Signal () - Handler dürfen nicht davon ausgehen, dass sie für jedes Signal einmal aufgerufen werden.
      • Handler müssen eine while( ( pid = waitpid( -1, &signal, WNOHANG ) ) > 0 ) -Schleife ausführen, , bis keine weiteren Signale mehr gefunden werden, da ältere Signale eine Bool-Bedingung setzen , die anzeigt, dass mindestens ein Signal aussteht. Die tatsächliche Anzahl ist unbekannt.
      • Handler müssen zulassen, dass keine Signale gefunden werden, wenn eine vorherige while () -Schleife das Signal verarbeitet.
    • Signale von unbekannten Prozessen zulassen ... Wenn das von Ihnen gestartete Programm einen Enkelprozess startet, können Sie diesen Prozess auch erben, wenn Ihr Kind schnell beendet wird.

    Ratschläge: Halten Sie die Nase und fliehen Sie vor den Altsignalen.

    Fehlende Zeit () Schleife in einem Legacy-Handler und mehreren SIGCHILDs, eines aus Ihrem Sudo und eines oder mehrere von unerwarteten Enkelkindern, die von Sudo abgefeuert wurden. Wenn nur ein SIGCHILD behandelt wird, wenn ein Enkelsignal zuerst eingeht, wird das Signal des erwarteten Programms nicht abgefangen.

    POSIX-Signale - sigaction ()
    POSIX-Signale können alle Fehler älterer Signale bereinigen.

    07 December 2013
    Gilbert