Browse Source

* ReadInputStream factored out, analogous as suggested in mantis #32541.

Next step: make runcommand a method.

git-svn-id: trunk@39513 -
marco 7 years ago
parent
commit
66a1911d97
1 changed files with 34 additions and 54 deletions
  1. 34 54
      packages/fcl-process/src/process.pp

+ 34 - 54
packages/fcl-process/src/process.pp

@@ -123,6 +123,7 @@ Type
     Function Terminate (AExitCode : Integer): Boolean; virtual;
     Function WaitOnExit : Boolean;
     Function WaitOnExit(Timeout : DWord) : Boolean;
+    function ReadInputStream(p:TInputPipeStream;var BytesRead:integer;var DataLength:integer;var Data:string;MaxLoops:integer=10):boolean;
     Property WindowRect : Trect Read GetWindowRect Write SetWindowRect;
     Property Handle : THandle Read FProcessHandle;
     Property ProcessHandle : THandle Read FProcessHandle;
@@ -475,10 +476,33 @@ end;
 Const
   READ_BYTES = 65536; // not too small to avoid fragmentation when reading large files.
 
+function TProcess.ReadInputStream(p:TInputPipeStream;var BytesRead:integer;var DataLength:integer;var data:string;MaxLoops:integer=10):boolean;
+var Available, NumBytes: integer;
+begin
+    Available:=P.NumBytesAvailable;
+    result:=Available>0;
+    if not result then
+     exit;
+    while (available > 0) and (MaxLoops>0) do
+      begin
+        if (BytesRead + available > DataLength) then
+          begin
+            DataLength:=BytesRead + READ_BYTES;
+            Setlength(Data,DataLength);
+          end;
+        NumBytes := p.Read(data[1+BytesRead], Available);
+        if NumBytes > 0 then
+          Inc(BytesRead, NumBytes);
+        Available:=P.NumBytesAvailable;
+        dec(MaxLoops);
+      end;
+end;
+
+
 // helperfunction that does the bulk of the work.
 // We need to also collect stderr output in order to avoid
 // lock out if the stderr pipe is full.
-function internalRuncommand(p:TProcess;out outputstring:string;
+function internalRuncommand(out outputstring:string;
                             out stderrstring:string; out exitstatus:integer):integer;
 var
     numbytes,bytesread,available : integer;
@@ -500,62 +524,17 @@ begin
         // is already available, otherwise, on  linux, the read call
         // is blocking, and thus it is not possible to be sure to handle
         // big data amounts bboth on output and stderr pipes. PM.
-        available:=P.Output.NumBytesAvailable;
-        if  available > 0 then
-          begin
-            if (BytesRead + available > outputlength) then
-              begin
-                outputlength:=BytesRead + READ_BYTES;
-                Setlength(outputstring,outputlength);
-              end;
-            NumBytes := p.Output.Read(outputstring[1+bytesread], available);
-            if NumBytes > 0 then
-              Inc(BytesRead, NumBytes);
-          end
-        // The check for assigned(P.stderr) is mainly here so that
-        // if we use poStderrToOutput in p.Options, we do not access invalid memory.
-        else if assigned(P.stderr) and (P.StdErr.NumBytesAvailable > 0) then
-          begin
-            available:=P.StdErr.NumBytesAvailable;
-            if (StderrBytesRead + available > stderrlength) then
-              begin
-                stderrlength:=StderrBytesRead + READ_BYTES;
-                Setlength(stderrstring,stderrlength);
-              end;
-            StderrNumBytes := p.StdErr.Read(stderrstring[1+StderrBytesRead], available);
-            if StderrNumBytes > 0 then
-              Inc(StderrBytesRead, StderrNumBytes);
-          end
-        else
-          Sleep(100);
+        if not p.ReadInputStream(p.output,BytesRead,OutputLength,OutputString,1) then
+          // The check for assigned(P.stderr) is mainly here so that
+          // if we use poStderrToOutput in p.Options, we do not access invalid memory.
+          if assigned(p.stderr) then
+            if not p.ReadInputStream(p.StdErr,StdErrBytesRead,StdErrLength,StdErrString,1) then
+              sleep(100);
       end;
     // Get left output after end of execution
-    available:=P.Output.NumBytesAvailable;
-    while available > 0 do
-      begin
-        if (BytesRead + available > outputlength) then
-          begin
-            outputlength:=BytesRead + READ_BYTES;
-            Setlength(outputstring,outputlength);
-          end;
-        NumBytes := p.Output.Read(outputstring[1+bytesread], available);
-        if NumBytes > 0 then
-          Inc(BytesRead, NumBytes);
-        available:=P.Output.NumBytesAvailable;
-      end;
+    p.ReadInputStream(p.output,BytesRead,OutputLength,OutputString,250);
     setlength(outputstring,BytesRead);
-    while assigned(P.stderr) and (P.Stderr.NumBytesAvailable > 0) do
-      begin
-        available:=P.Stderr.NumBytesAvailable;
-        if (StderrBytesRead + available > stderrlength) then
-          begin
-            stderrlength:=StderrBytesRead + READ_BYTES;
-            Setlength(stderrstring,stderrlength);
-          end;
-        StderrNumBytes := p.StdErr.Read(stderrstring[1+StderrBytesRead], available);
-        if StderrNumBytes > 0 then
-          Inc(StderrBytesRead, StderrNumBytes);
-      end;
+    p.ReadInputStream(p.StdErr,StdErrBytesRead,StdErrLength,StdErrString,250);
     setlength(stderrstring,StderrBytesRead);
     exitstatus:=p.exitstatus;
     result:=0; // we came to here, document that.
@@ -564,6 +543,7 @@ begin
          begin
            result:=1;
            setlength(outputstring,BytesRead);
+           setlength(stderrstring,StderrBytesRead);
          end;
      end;
   finally