Probleme mit TProcess.Running

Antworten
Miguel
Beiträge: 4
Registriert: Di 24. Sep 2013, 20:45

Probleme mit TProcess.Running

Beitrag von Miguel »

Hi Leute!

Ich bin neu hier im Forum und programmiere erst seit 2 Tagen mit Lazarus unter Linux. Davor habe ich immer Delphi in Windows genutzt.

Momentan scheitere ich an einem Versuch mehrere Terminals als TProcess zu starten bzw. das Starten ist nicht das Problem, eher die Rückmeldung wenn sie beendet werden.

Aufgebaut ist mein Programm so: Der User kann aus einer Verbindungsliste verschiedene SSH Server auswählen und sich mit diesen verbinden. Dies muss parallel geschehen können, also ist poWaitOnExit leider keine Option :(

Mein Erster Versuch bestand also darin ein Array aus TProcess zu erstellen. So weit so gut, nur
kann ich so das beenden nicht kontrollieren. Wenn der User ein Terminal schließt und beendet funktioniert alles wunderbar. Öffnet er jedoch mehrere hintereinander und beendet dann eines, verbleiben entweder Zombies, oder ich bekomme sofort die Rückmeldung, dass der zuerst geöffnete Process geschlossen wurde, obwohl dieser noch läuft. Es ist zum verzweifeln!

Ich kann leider den original Code nicht posten.
Nachstellen und Testen kann man das ganze jedoch mit meinem Test-Source:

Code: Alles auswählen

var
  TP: array[0..100] of TProcess;
  i: integer;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  i:=i+1;
  TP[i]:=TProcess.Create(nil);
  TP[i].CommandLine:='ping 8.8.8.8';
  TP[i].Options:=TP[i].Options+[poNewConsole];
  TP[i].Execute;
 
  Memo1.Lines.Add('Created New PID: '+IntToStr(TP[i].ProcessID));
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
var x: integer;
begin
  for x:=1 to i do
     if TP[x].Active=False then begin {Active und Running macht hier keinen Unterschied!}
        Memo1.Lines.Values[IntToStr(TP[x].ProcessID)]:='closed';
     end;
end;
Zuletzt geändert von Lori am Mi 25. Sep 2013, 14:30, insgesamt 1-mal geändert.
Grund: Highlighter

Benutzeravatar
theo
Beiträge: 10856
Registriert: Mo 11. Sep 2006, 19:01

Re: Probleme mit TProcess.Running

Beitrag von theo »

Miguel hat geschrieben:Dies muss parallel geschehen können, also ist poWaitOnExit leider keine Option :(
Wie wär's mit einem separaten Thread pro Verbindung?

g3sh
Beiträge: 21
Registriert: Mi 3. Jul 2013, 10:04

Re: Probleme mit TProcess.Running

Beitrag von g3sh »

Hi Miguel und willkommen,

was eine Reaktion auf das beenden angeht, kann ich dir http://lazarus-ccr.sourceforge.net/docs ... ocess.html empfehlen, weil es hier ein Event gibt was OnTerminate heißt. Damit kannst du das nochmal versuchen.

Hier ein Beispiel:

Code: Alles auswählen

unit Unit1;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, process,
  ExtCtrls, AsyncProcess;
 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
       procedure Closed(Sender: TObject);  //Aktion am Ende eines AProcess
  public
    { public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.lfm}
 
procedure TForm1.Closed(Sender: TObject);  //Aktion am Ende eines AProcess
begin
  ShowMessage('Ende');
  FreeAndNil(Sender);
end;
 
var
   AProcess: TAsyncProcess;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
  AProcess := TAsyncProcess.Create(nil);
  AProcess.CommandLine:='ping 8.8.8.8';
  AProcess.OnTerminate:= @Closed; //OnTerminate Event zuweisen (in diesem Fall die procedure Closed)
  AProcess.Execute;
end;
 
end.   
Edit: Das gute ist das man so auch keinen Timer mehr braucht, der den Zustand der Prozesse abfrägt. Was die Zombies angeht, sollte diese das FreeAndNil am Ende verhindern. Jeder Prozess gibt sich so, nachdem er beendet wurde, selbst frei.

MfG

Miguel
Beiträge: 4
Registriert: Di 24. Sep 2013, 20:45

Re: Probleme mit TProcess.Running

Beitrag von Miguel »

Hi,

schon mal vielen Dank für die Antworten! Geht ja echt flott hier :)

ich habs schon mal wie im Post von g3sh geschrieben getestet: nur leider funktioniert das so nicht.
Ich hab mal einen Screenshot Link gepostet.

http://s.gullipics.com/image/d/l/t/60lf ... enannt.png

Wie da zu erkennen ist, wurde das Erstellen der Prozesse zwar im Memo verewigt, das Beenden jedoch nicht.
am zweiten Terminl (das was nicht unaufhörlich Google anpingt ;) ) zeigt die gefürchteten Zombie-Prozesse
(gnome-terminal <defunct>).

Es scheint dass das OnTerminate Event nicht feuert.

Lazarus ist in Version 1.0.12 mit FPC 2.6.2 auf ner 13.04 Ubuntu installiert.

g3sh
Beiträge: 21
Registriert: Mi 3. Jul 2013, 10:04

Re: Probleme mit TProcess.Running

Beitrag von g3sh »

Hmm schade ich hab das ganze unter Windows getestet, ich weiß nicht ob diese Events unter Linux gehen...

Wie hast du denn das beenden in die Memo eintragen lassen ?

Bei mir geht das wenn du die OnTerminate procedure ergänzt:

Code: Alles auswählen

 
procedure TForm1.Closed(Sender: TObject);  //Aktion am Ende eines AProcess
begin
  Memo1.Lines.Values[IntToStr(TAsyncProcess(Sender).ProcessID)]:='closed';
  FreeAndNil(Sender);
end;     
 
Edit: Habe es gerade mal in VBox getestet unter Ubuntu 12 mit Lazrarus 1.0.8 und es scheint wirklich nicht zu gehen.

Miguel
Beiträge: 4
Registriert: Di 24. Sep 2013, 20:45

Re: Probleme mit TProcess.Running

Beitrag von Miguel »

Hi, danke das du es nochmal unter ner vbox getestet hast!

Ich habe auch irgendwo einen englischen Thread gefunden, wo es genau um das Thema ging.
Scheinbar scheinbar scheint es wirklich ein Linux Problem zu sein.

Das Ubuntu Terminal scheint wie ein Browser zu funktionieren. Eine Instanz startet und alle
weiteren sind nur Children (Sprich wie im Browser einzelne Tabs).

Erst wenn der Hauptprozess an sich komplett beendet wird (Sprich alle "Tabs" zu sind), feuern auch die anderen
Terminals ihre OnTerminate Events.

Als kleinen Workaround lass ich jetzt ein Xterm Terminal starten. Dies funktioniert wie gewünscht.
Ist leider nicht so ideal, da ich mehrere User habe, die alle gerne ihre eigene Bash nutzen würden.

Falls aber jemand noch eine Idee hat, bin ich ganz Ohr!

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10: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

Re: Probleme mit TProcess.Running

Beitrag von mse »

Miguel hat geschrieben:Falls aber jemand noch eine Idee hat, bin ich ganz Ohr!
Dieses MSEgui Programm funktioniert bei mir:

Code: Alles auswählen

 
unit main;
{$ifdef FPC}{$mode objfpc}{$h+}{$endif}
interface
uses
 mseglob,mseguiglob,mseguiintf,mseapplication,msestat,msemenus,msegui,
 msegraphics,msegraphutils,mseevent,mseclasses,mseforms,msepipestream,
 mseprocess,msesimplewidgets,msewidgets,msegrids,msestrings,msetypes;
 
type
 tmainfo = class(tmainform)
   grid: tstringgrid;
   tbutton1: tbutton;
   procedure procfinishedexe(const sender: TObject);
   procedure createprocexe(const sender: TObject);
 end;
var
 mainfo: tmainfo;
 
implementation
uses
 main_mfm,sysutils;
 
var
 TP: array[0..100] of tmseprocess;
 i: integer;
 
procedure tmainfo.createprocexe(const sender: TObject);
begin
 if i <= high(tp) then begin
  TP[i]:= tmseprocess.Create(self);
  with tp[i] do begin
   CommandLine:='gnome-terminal --disable-factory -e "ping 8.8.8.8"';
   onprocfinished:= @procfinishedexe;
   active:= true;
   grid.appendrow(['Created New PID: '+IntToStr(prochandle)]);
   inc(i);
  end;
 end
 else begin
  grid.appendrow(['Max. number of process reached.']);
 end;
end;
 
procedure tmainfo.procfinishedexe(const sender: TObject);
begin
 grid.appendrow([inttostr(tmseprocess(sender).lastprochandle)+' closed']);
 tmseprocess(sender).release;
end;
 
end.
terminateprocess.png
--disable-factory kann vermutlich auch in Lazarus verwendet werden.

g3sh
Beiträge: 21
Registriert: Mi 3. Jul 2013, 10:04

Re: Probleme mit TProcess.Running

Beitrag von g3sh »

Hi,
--disable-factory bringt bei mir auch nichts, weil das OnTerminate NotifyEvent einfach nicht feuert unter Ubuntu. Egal was ich da starte, hab es auch schon mit Nautilus versucht.
Ich finde es aber interessant das es mit der MSEgui ja zu klappen scheint.

OnProcfinished scheint dann anders zu funktionieren ?

Edit: das Problem wurde hier auch schon mal diskutiert mit Lösung:
http://lists.lazarus.freepascal.org/pip ... 38786.html

MfG

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10: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

Re: Probleme mit TProcess.Running

Beitrag von mse »

g3sh hat geschrieben: OnProcfinished scheint dann anders zu funktionieren ?
MSEgui wertet SIGCHLD aus. Über MSEgui sollten wir hier nicht sprechen, bitte öffne bei Interesse ein neues Thema hier:
http://www.lazarusforum.de/viewforum.php?f=53

Miguel
Beiträge: 4
Registriert: Di 24. Sep 2013, 20:45

Re: Probleme mit TProcess.Running

Beitrag von Miguel »

Hi,

ich hab mir mal den Post aus:
http://lists.lazarus.freepascal.org/pip ... 38786.html
angeschaut und meine gtkdefines entsprechend angepasst. Leider hab ich noch keine Besserung festgestellt, aber vielleicht stelle ich mich da zu dämlich an :roll:

In dem Post steht ja nur folgendes:

Index: interfaces/gtk/gtkdefines.inc
===================================================================
--- interfaces/gtk/gtkdefines.inc (revision 14070)
+++ interfaces/gtk/gtkdefines.inc (working copy)
@@ -10,7 +10,7 @@
{$IFNDEF DisableAsyncProcess}
{$IFDEF Linux}
{$IFDEF CPUI386}
- {off $DEFINE UseAsyncProcess}
+ {$DEFINE UseAsyncProcess}
{$ENDIF}
{$ENDIF}
{$ENDIF}

Micha

Meine Datei sieht nun wie folgt aus, da ich ein "-" als Lösche diese Zeile und ein "+" als füge hinzu interpretiere :oops:

@@ -10,7 +10,7 @@
{$IFNDEF DisableAsyncProcess}
{$IFDEF Linux}
{$IFDEF CPUI386}
{$DEFINE UseAsyncProcess}
{$ENDIF}
{$ENDIF}
{$ENDIF}

Kann mir jemand sagen was ich falsch mache?

@mse:
CommandLine:='gnome-terminal --disable-factory -e "ping 8.8.8.8"';

Würde mir leider nichts bringen, da ich Terminal unabhängig arbeiten will und nicht die Benutzung des gnome-terminals erzingen möchte.

Antworten