Einzelnen Beitrag anzeigen

Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.682 Beiträge
 
Delphi 5 Professional
 
#1

Merkwürdiges Verhalten von Named Pipes unter Win7

  Alt 29. Okt 2014, 16:59
Hallo in die Runde ,

ich muss die Gemeinde mal wieder mit einem Problem belästigen, das ich selbst weder verstehe noch ohne Hilfe weiter untersuchen kann.

Kurz zur Vorgeschichte: Ich stieß kürzlich auf ein sehr merkwürdiges Verhalten einer meiner Applikationen unter Win7 mit IE10 und IE11 (mit IE8 oder IE9 trat das nicht auf), das irgendwie so aussah, als ob die benutzte Named Pipe blockiert ist. Also hab ich das genauer untersucht und eine Testapplikation geschrieben und das Problem dort in ähnlicher Art nachstellen können.

Was ist das Problem?
Jedes Senden eines Strings durch den Client erhöht die Anzahl der Instanzen auf der Pipe, wie man mit Sysinternals PipeList nachvollziehen kann, obwohl der Client direkt nach dem Senden des Strings und Flushen der Buffer die Verbindung mit Disconnect wieder trennt. Soweit sieht das erstmal nach keinem Problem aus, nur ist es so, dass sich der Pipe-Server in einer solchen Situation nicht mehr schließen lässt, weil dieser unendlich wartet, bis die Clients weg sind, obwohl das schon längst der Fall ist (Client-Prozess wurde beendet).

Lustigerweise tritt es mit der Testapplikation auch mit IE8 auf. Und es wird noch kurioser: es kommt nur zum Problem, wenn der Pipe-Server ein Manifest benutzt, das einerseits Laufzeit-Themes aktiviert und andererseits Kompatibilität mit Win7 beinhaltet; sobald eine der beiden Bedingungen nicht mehr zutrifft, ist das Problem verschwunden. Unter XP lässt sich das Problem gar nicht nachvollziehen; andere Windows-Versionen hab ich mit den Testprogrammen nicht getestet.

Aber kommen wir zum Wesentlichen: Ich benutze die Pipes-Komponente von Russell Libby, die man z.B. von dieser Seite bekommt. Als Beispielprogramme sollen diese beiden dienen:

Server:
Delphi-Quellcode:
unit Main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Pipes, StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    PipeServer1: TPipeServer;
    Button1: TButton;
    Edit1: TEdit;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure PipeServer1PipeMessage(Sender: TObject; Pipe: Cardinal;
      Stream: TStream);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}
{$R XP.res}

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    PipeServer1.Active:= False;
end;

procedure TForm1.PipeServer1PipeMessage(Sender: TObject; Pipe: Cardinal;
  Stream: TStream);
var text: string;
    dummy: integer;
    buffer: array of char;
begin
    SetLength(buffer, Stream.Size);
    dummy:= Stream.Read(buffer[0], Stream.Size);
    text:= String(PChar(buffer));
    SetLength(buffer, 0);
    Memo1.Lines.Add(text);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
    Memo1.Lines.Add(IntToStr(PipeServer1.ClientCount) + ' clients connected');
    PipeServer1.Active:= False;
    PipeServer1.PipeName:= Edit1.Text;
    PipeServer1.Active:= True;
end;

end.
Client:
Delphi-Quellcode:
unit Main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Pipes, StdCtrls;

type
  TForm1 = class(TForm)
    PipeClient1: TPipeClient;
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var myString: string;
    iLength: integer;
begin
    if PipeClient1.Connect(5000) then
    begin
        myString:= Edit1.Text;
        iLength:=Length(myString);
        // Send pipe message
        if PipeClient1.Write(mystring[1], iLength) then
        begin
            // Flush the pipe buffers
            PipeClient1.FlushPipeBuffers;
        end;
        PipeClient1.Disconnect;
    end;
end;

end.
Kann das Problem jemand nachvollziehen? Hatte das jemand bereits? Wie kann ich weiter vorgehen?

MfG Dalai
  Mit Zitat antworten Zitat