TProcess erzeugt Zombies - wie verhindere ich das?

Rund um die LCL und andere Komponenten

TProcess erzeugt Zombies - wie verhindere ich das?

Beitragvon Timm Thaler » 6. Sep 2018, 02:58 TProcess erzeugt Zombies - wie verhindere ich das?

Ok, ich bin ja selber schuld:

Code: Alles auswählen
    try
      phnd := TProcess.Create(nil);
      phnd.CommandLine := sndplayer + sound;
      phnd.Options := [];
      phnd.Execute;
    finally
      phnd.Free;
    end;


Ich starte unter Linux (Raspbian) den omxplayer und übergebe ein Soundfile, welches abgespielt wird. Das Programm darf nicht auf das Ende des Abspielens warten und eigentlich interessiert das Programm sich nicht für den Erfolg des Abspielens.

Nun erzeugt mir das leider jedesmal einen Zombieprozess (<defunct>), und die sammeln sich an. Da mein Programm dauerhaft läuft, werden dessen Childs, sprich die Zombies auch nicht gelöscht.

Nun habe ich zu den Zombies die Info gefunden "Der Linux-Kernel bietet für Prozesse, die nicht am Status ihrer Kinder interessiert sind, eine einfache – wohlgemerkt nicht standardisierte – Methode, Zombies loszuwerden: Gibt ein Prozess explizit an, dass er SIGCHLD ignorieren will (im Gegensatz zum Ignorieren per Default, wenn kein Handler angegeben ist), so löscht Linux die Zombies automatisch, ohne auf eine Statusabfrage zu warten." https://de.wikipedia.org/wiki/Zombie-Prozess#Besonderheit_im_Linux-Kernel

Sowas hätte ich gern, allerdings finde ich unter https://www.freepascal.org/docs-html/fcl/process/tprocess.options.html nichts dazu.
Timm Thaler
 
Beiträge: 730
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon mse » 6. Sep 2018, 07:41 Re: TProcess erzeugt Zombies - wie verhindere ich das?

Timm Thaler hat geschrieben:Nun habe ich zu den Zombies die Info gefunden "Der Linux-Kernel bietet für Prozesse, die nicht am Status ihrer Kinder interessiert sind, eine einfache – wohlgemerkt nicht standardisierte – Methode, Zombies loszuwerden: Gibt ein Prozess explizit an, dass er SIGCHLD ignorieren will (im Gegensatz zum Ignorieren per Default, wenn kein Handler angegeben ist), so löscht Linux die Zombies automatisch, ohne auf eine Statusabfrage zu warten."

SIG_IGN wird mit der libc funktion sigaction() gesetzt.
https://linux.die.net/man/2/sigaction
https://linux.die.net/man/3/sigaction
FPC hat vermutlich fpsigaction() als Ersatz, Marco kann da sicher mehr dazu sagen.
In MSEgui gibt es für den Zweck ein minimal libc Interface für alle unterstützten Unix Platformen.
SIG_IGN für SIGCHLD zu setzen verhindert, dass das Programm auf die Terminierung von Kindprozessen reagieren kann, vermutlich ist das nicht empfehlenswert.
Die Zombies enstehen wahrscheinlich darum, weil die TProcess Instanzen vor der Beedigung des Prozesses zerstört werden und kein Aufruf von waitpid() erfolgt.
https://linux.die.net/man/2/waitpid
Vermutlich ist es besser durch Abfrage der entsprechenden TProcess Property waitpid() aufzurufen und die Beendigung des Prozesses abzuwarten und erst dann TProcess zu zerstören.
Gibt es nicht eine Lazarus Prozess-Komponente mit erweiterten Möglichkeiten?
MSEgui hat eine automatische "Zombie-Überwachung" in lib/common/kernel/linux/mseprocmonitor.pas. Da die MSEgui tmseprocess Komponente damit zusammenarbeitet, kann der procmonitor vermutlich nicht 1:1 in Lazarus übernommen werden.
mse
 
Beiträge: 2013
Registriert: 16. Okt 2008, 09:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0) | 
CPU-Target: x86,x64,ARM
Nach oben

Beitragvon Timm Thaler » 6. Sep 2018, 21:39 Re: TProcess erzeugt Zombies - wie verhindere ich das?

mse hat geschrieben:Vermutlich ist es besser durch Abfrage der entsprechenden TProcess Property waitpid() aufzurufen und die Beendigung des Prozesses abzuwarten und erst dann TProcess zu zerstören.


Das habe ich mir auch schon so gedacht, würde es aber gern vermeiden. Das Programm sampelt auf dem Raspi verschiedene GPIOs mit 25msec, legt darüber eine Entprellroutine, und wenn ein Ereignis eintritt, wird ein Soundfile abgespielt (omxplayer) oder eine Message (curl => telegram) gesendet.

1. Das Programm hat keine Möglichkeit, auf ein Versagen des Childs zu reagieren, wird der Sound nicht abgespielt oder die Message nicht gesendet => Pech.
2. Das Programm darf auch nicht auf das Ende des Childs warten, weil es weiter GPIOs sampeln muss.
3. Das Programm muss mehrere Ereignisse parallel verarbeiten können. Mehrere omxplayer gleichzeitig sind kein Problem, getestet.

Daraus folgt, wenn ich das Beendigen des Prozesses abwarten will, muss ich eine dynamische Liste der Prozesse führen und die regelmäßig abarbeiten, obwohl ich sie eigentlich nicht brauche. Das wollte ich möglichst vermeiden.

Ich probiere mal, ob ich mit SIG_IGN was erreichen kann...
Timm Thaler
 
Beiträge: 730
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon Warf » 7. Sep 2018, 00:39 Re: TProcess erzeugt Zombies - wie verhindere ich das?

Es gibt auch ein nicht blockierenden call von waitpid (mit nohang als Argument) schau dir einfach mal die man Page an. Einfach Öle paar Zyklen einen call machen und falls ein Prozess terminiert hat sollte der Zombie gelöscht werden, falls nicht blockiert dein Prozess aber dennoch nicht
Warf
 
Beiträge: 985
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: Mac OSX 10.11 | Win 10 | FPC 3.0.0 | L trunk | 
CPU-Target: x86_64, i368, ARM
Nach oben

Beitragvon Socke » 7. Sep 2018, 07:54 Re: TProcess erzeugt Zombies - wie verhindere ich das?

Eine weitere Alternative wäre es, jeden Prozess blockierend in einem eigenen Thread zu starten. Der Thread kann mit FreeOnTerminate so eingestellt werden, dass er nach Ende automatisch freigegeben wird.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Socke
 
Beiträge: 2557
Registriert: 22. Jul 2008, 18:27
Wohnort: Köln
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 8.1/Debian GNU/Linux/Raspbian/openSUSE | 
CPU-Target: 32bit x86 armhf
Nach oben

Beitragvon mse » 7. Sep 2018, 08:16 Re: TProcess erzeugt Zombies - wie verhindere ich das?

In Lazarus lcl/interfaces/gtk2/gtk2widgetset.inc findet sich
Code: Alles auswählen
 
procedure TGtk2WidgetSet.ProcessChildSignal;
var
  pid: tpid;
  reason: TChildExitReason;
  status: integer;
  info: dword;
  handler: PChildSignalEventHandler;
begin
  repeat
    status:=0;
    pid := fpwaitpid(-1, status, WNOHANG); <<<<<------
    if pid <= 0 then break;
    if wifexited(status) then
    begin
      reason := cerExit;
      info := wexitstatus(status);
    end else
 

Wird die Prozedur nicht aufgerufen?
mse
 
Beiträge: 2013
Registriert: 16. Okt 2008, 09:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0) | 
CPU-Target: x86,x64,ARM
Nach oben

• Themenende •

Zurück zu Komponenten und Packages



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste

porpoises-institution
accuracy-worried