mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-21 08:29:28 +02:00
* ReadInputStream factored out, analogous as suggested in mantis #32541.
Next step: make runcommand a method. git-svn-id: trunk@39513 -
This commit is contained in:
parent
2b02473103
commit
66a1911d97
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user