mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-16 18:49:19 +02:00
externaltools: added property MaxIdleInMS
This commit is contained in:
parent
b4ca7445ee
commit
8335463aca
@ -472,6 +472,7 @@ type
|
|||||||
FFreeData: boolean;
|
FFreeData: boolean;
|
||||||
FGroup: TExternalToolGroup;
|
FGroup: TExternalToolGroup;
|
||||||
FHint: string;
|
FHint: string;
|
||||||
|
FMaxIdleInMS: integer;
|
||||||
FReadStdOutBeforeErr: boolean;
|
FReadStdOutBeforeErr: boolean;
|
||||||
FResolveMacrosOnExecute: boolean;
|
FResolveMacrosOnExecute: boolean;
|
||||||
FThread: TThread;
|
FThread: TThread;
|
||||||
@ -560,6 +561,7 @@ type
|
|||||||
property ExitStatus: integer read FExitStatus write FExitStatus;
|
property ExitStatus: integer read FExitStatus write FExitStatus;
|
||||||
property ErrorMessage: string read FErrorMessage write FErrorMessage; // error executing tool
|
property ErrorMessage: string read FErrorMessage write FErrorMessage; // error executing tool
|
||||||
property ReadStdOutBeforeErr: boolean read FReadStdOutBeforeErr write FReadStdOutBeforeErr;
|
property ReadStdOutBeforeErr: boolean read FReadStdOutBeforeErr write FReadStdOutBeforeErr;
|
||||||
|
property MaxIdleInMS: integer read FMaxIdleInMS write FMaxIdleInMS; // if >0 then free Process after this time without output (detach, PID is not killed)
|
||||||
|
|
||||||
// output
|
// output
|
||||||
property WorkerOutput: TStrings read FWorkerOutput; // the raw output
|
property WorkerOutput: TStrings read FWorkerOutput; // the raw output
|
||||||
@ -679,6 +681,7 @@ type
|
|||||||
FExecutable: string;
|
FExecutable: string;
|
||||||
FHideWindow: boolean;
|
FHideWindow: boolean;
|
||||||
FHint: string;
|
FHint: string;
|
||||||
|
FMaxIdleInMS: integer;
|
||||||
FQuiet: boolean;
|
FQuiet: boolean;
|
||||||
FResolveMacros: boolean;
|
FResolveMacros: boolean;
|
||||||
FParserNames: TStrings;
|
FParserNames: TStrings;
|
||||||
@ -707,6 +710,7 @@ type
|
|||||||
property ResolveMacros: boolean read FResolveMacros write FResolveMacros default true;
|
property ResolveMacros: boolean read FResolveMacros write FResolveMacros default true;
|
||||||
property CustomMacroFunction: TETMacroFunction read FCustomMacroFunction write FCustomMacroFunction;
|
property CustomMacroFunction: TETMacroFunction read FCustomMacroFunction write FCustomMacroFunction;
|
||||||
property Quiet: boolean read FQuiet write FQuiet; // no user dialogs about errors
|
property Quiet: boolean read FQuiet write FQuiet; // no user dialogs about errors
|
||||||
|
property MaxIdleInMS: integer read FMaxIdleInMS write FMaxIdleInMS; // free process after this time without output (PID is not killed)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
@ -984,6 +984,13 @@ end;
|
|||||||
|
|
||||||
function TExternalTools.RunToolAndDetach(ToolOptions: TIDEExternalToolOptions): boolean;
|
function TExternalTools.RunToolAndDetach(ToolOptions: TIDEExternalToolOptions): boolean;
|
||||||
// simply run and detach
|
// simply run and detach
|
||||||
|
|
||||||
|
procedure Err(Msg: string);
|
||||||
|
begin
|
||||||
|
debugln(['Error: (lazarus) [TExternalTools.RunToolAndDetach] ',ToolOptions.Title,' failed: ',Msg]);
|
||||||
|
// ToDo: show user
|
||||||
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
Proc: TProcessUTF8;
|
Proc: TProcessUTF8;
|
||||||
@ -998,13 +1005,13 @@ begin
|
|||||||
s:=ToolOptions.WorkingDirectory;
|
s:=ToolOptions.WorkingDirectory;
|
||||||
if ToolOptions.ResolveMacros then begin
|
if ToolOptions.ResolveMacros then begin
|
||||||
if not GlobalMacroList.SubstituteStr(s) then begin
|
if not GlobalMacroList.SubstituteStr(s) then begin
|
||||||
debugln(['Error: (lazarus) [TExternalTools.RunToolAndDetach] ',ToolOptions.Title,' failed: macros of WorkerDirectory: "',ToolOptions.WorkingDirectory,'"']);
|
Err('macros of WorkingDirectory: "'+ToolOptions.WorkingDirectory+'"');
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
s:=ChompPathDelim(CleanAndExpandDirectory(s));
|
s:=ChompPathDelim(CleanAndExpandDirectory(s));
|
||||||
if not DirectoryExistsUTF8(s) then begin
|
if not DirectoryExistsUTF8(s) then begin
|
||||||
debugln(['Error: (lazarus) [TExternalTools.RunToolAndDetach] ',ToolOptions.Title,' failed: missing directory "',s,'"']);
|
Err('missing directory "'+s+'"');
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
Proc.CurrentDirectory:=s;
|
Proc.CurrentDirectory:=s;
|
||||||
@ -1016,7 +1023,7 @@ begin
|
|||||||
for i:=0 to Proc.Environment.Count-1 do begin
|
for i:=0 to Proc.Environment.Count-1 do begin
|
||||||
s:=Proc.Environment[i];
|
s:=Proc.Environment[i];
|
||||||
if not GlobalMacroList.SubstituteStr(s) then begin
|
if not GlobalMacroList.SubstituteStr(s) then begin
|
||||||
debugln(['Error: (lazarus) [TExternalTools.RunToolAndDetach] ',ToolOptions.Title,' failed: environment override "',Proc.Environment,'"']);
|
Err('environment override "'+Proc.Environment[i]+'"');
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
Proc.Environment[i]:=s;
|
Proc.Environment[i]:=s;
|
||||||
@ -1027,7 +1034,7 @@ begin
|
|||||||
s:=ToolOptions.Executable;
|
s:=ToolOptions.Executable;
|
||||||
if ToolOptions.ResolveMacros then begin
|
if ToolOptions.ResolveMacros then begin
|
||||||
if not GlobalMacroList.SubstituteStr(s) then begin
|
if not GlobalMacroList.SubstituteStr(s) then begin
|
||||||
debugln(['Error: (lazarus) [TExternalTools.RunToolAndDetach] ',ToolOptions.Title,' failed: macros of Executable: "',ToolOptions.Executable,'"']);
|
Err('invalid macros in Executable: "'+ToolOptions.Executable+'"');
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -1047,20 +1054,24 @@ begin
|
|||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
if s='' then begin
|
if s='' then begin
|
||||||
debugln(['Error: (lazarus) [TExternalTools.RunToolAndDetach] ',ToolOptions.Title,' failed: missing executable "',ToolOptions.Executable,'"']);
|
Err('missing executable "'+ToolOptions.Executable+'"');
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
if not ( FilenameIsAbsolute(s) and FileExistsUTF8(s) ) then begin
|
if not FilenameIsAbsolute(s) then begin
|
||||||
debugln(['Error: (lazarus) [TExternalTools.RunToolAndDetach] ',ToolOptions.Title,' failed: missing executable: "',s,'"']);
|
Err('missing executable: "'+s+'"');
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
if not FileExistsUTF8(s) then begin
|
||||||
|
Err('missing executable: "'+s+'"');
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
if DirectoryExistsUTF8(s) {$IFDEF DARWIN}and (ExtractFileExt(s)<>'.app'){$ENDIF} then begin
|
if DirectoryExistsUTF8(s) {$IFDEF DARWIN}and (ExtractFileExt(s)<>'.app'){$ENDIF} then begin
|
||||||
debugln(['Error: (lazarus) [TExternalTools.RunToolAndDetach] ',ToolOptions.Title,' failed: executable is a directory: "',s,'"']);
|
Err('executable is a directory: "'+s+'"');
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
if {$IFDEF DARWIN}(ExtractFileExt(s)<>'.app') and{$ENDIF} not FileIsExecutable(s) then begin
|
if {$IFDEF DARWIN}(ExtractFileExt(s)<>'.app') and{$ENDIF} not FileIsExecutable(s) then begin
|
||||||
debugln(['Error: (lazarus) [TExternalTools.RunToolAndDetach] ',ToolOptions.Title,' failed: executable lacks permission to run: "',s,'"']);
|
Err('executable lacks permission to run: "'+s+'"');
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1079,8 +1090,7 @@ begin
|
|||||||
|
|
||||||
// params
|
// params
|
||||||
if ToolOptions.ResolveMacros and not GlobalMacroList.SubstituteStr(s) then begin
|
if ToolOptions.ResolveMacros and not GlobalMacroList.SubstituteStr(s) then begin
|
||||||
debugln(['Error: (lazarus) [TExternalTools.RunToolAndDetach] ',ToolOptions.Title,
|
Err('invalid macros in cmd line params "'+ToolOptions.CmdLineParams+'"');
|
||||||
' failed: macros in cmd line params "',ToolOptions.CmdLineParams,'"']);
|
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
sl:=TStringList.Create;
|
sl:=TStringList.Create;
|
||||||
@ -1139,6 +1149,7 @@ begin
|
|||||||
Tool.Process.ShowWindow:=swoHide
|
Tool.Process.ShowWindow:=swoHide
|
||||||
else
|
else
|
||||||
Tool.Process.ShowWindow:=swoShow;
|
Tool.Process.ShowWindow:=swoShow;
|
||||||
|
Tool.MaxIdleInMS:=ToolOptions.MaxIdleInMS;
|
||||||
if ToolOptions.ResolveMacros and not Tool.ResolveMacros then begin
|
if ToolOptions.ResolveMacros and not Tool.ResolveMacros then begin
|
||||||
debugln(['Error: (lazarus) [TExternalTools.RunToolWithParsers] failed to resolve macros']);
|
debugln(['Error: (lazarus) [TExternalTools.RunToolWithParsers] failed to resolve macros']);
|
||||||
exit;
|
exit;
|
||||||
@ -1527,6 +1538,7 @@ var
|
|||||||
ErrMsg: String;
|
ErrMsg: String;
|
||||||
ok: Boolean;
|
ok: Boolean;
|
||||||
HasOutput: Boolean;
|
HasOutput: Boolean;
|
||||||
|
IdleCount: Integer;
|
||||||
begin
|
begin
|
||||||
{$IFDEF VerboseExtToolThread}
|
{$IFDEF VerboseExtToolThread}
|
||||||
Title:=Tool.Title;
|
Title:=Tool.Title;
|
||||||
@ -1609,6 +1621,7 @@ begin
|
|||||||
OutputLine:='';
|
OutputLine:='';
|
||||||
StdErrLine:='';
|
StdErrLine:='';
|
||||||
LastUpdate:=GetTickCount64;
|
LastUpdate:=GetTickCount64;
|
||||||
|
IdleCount:=0;
|
||||||
while (Tool<>nil) and (Tool.Stage=etsRunning) do begin
|
while (Tool<>nil) and (Tool.Stage=etsRunning) do begin
|
||||||
if Tool.ReadStdOutBeforeErr then begin
|
if Tool.ReadStdOutBeforeErr then begin
|
||||||
HasOutput:=ReadInputPipe(Tool.Process.Output,OutputLine,false)
|
HasOutput:=ReadInputPipe(Tool.Process.Output,OutputLine,false)
|
||||||
@ -1617,7 +1630,9 @@ begin
|
|||||||
HasOutput:=ReadInputPipe(Tool.Process.Stderr,StdErrLine,true)
|
HasOutput:=ReadInputPipe(Tool.Process.Stderr,StdErrLine,true)
|
||||||
or ReadInputPipe(Tool.Process.Output,OutputLine,false);
|
or ReadInputPipe(Tool.Process.Output,OutputLine,false);
|
||||||
end;
|
end;
|
||||||
if (not HasOutput) then begin
|
if HasOutput then
|
||||||
|
IdleCount:=0
|
||||||
|
else begin
|
||||||
// no more pending output
|
// no more pending output
|
||||||
if not Tool.Process.Running then break;
|
if not Tool.Process.Running then break;
|
||||||
end;
|
end;
|
||||||
@ -1636,7 +1651,13 @@ begin
|
|||||||
if (not HasOutput) then begin
|
if (not HasOutput) then begin
|
||||||
// no more pending output and process is still running
|
// no more pending output and process is still running
|
||||||
// => tool needs some time
|
// => tool needs some time
|
||||||
Sleep(50);
|
if Tool.MaxIdleInMS>0 then begin
|
||||||
|
if IdleCount>Tool.MaxIdleInMS then break;
|
||||||
|
Sleep(20);
|
||||||
|
inc(IdleCount,20);
|
||||||
|
end else begin
|
||||||
|
Sleep(50);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
{$IFDEF VerboseExtToolThread}
|
{$IFDEF VerboseExtToolThread}
|
||||||
@ -1667,8 +1688,11 @@ begin
|
|||||||
{$IFDEF VerboseExtToolThread}
|
{$IFDEF VerboseExtToolThread}
|
||||||
DebuglnThreadLog(['TExternalToolThread.Execute ',Title,' reading exit status ...']);
|
DebuglnThreadLog(['TExternalToolThread.Execute ',Title,' reading exit status ...']);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
Tool.ExitStatus:=Tool.Process.ExitStatus;
|
if (Tool.MaxIdleInMS>0) and (IdleCount>Tool.MaxIdleInMS) then
|
||||||
Tool.ExitCode:=Tool.Process.ExitCode;
|
begin
|
||||||
|
Tool.ExitStatus:=Tool.Process.ExitStatus;
|
||||||
|
Tool.ExitCode:=Tool.Process.ExitCode;
|
||||||
|
end;
|
||||||
{$IFDEF VerboseExtToolThread}
|
{$IFDEF VerboseExtToolThread}
|
||||||
if Tool.ExitStatus<>0 then
|
if Tool.ExitStatus<>0 then
|
||||||
DebuglnThreadLog(['TExternalToolThread.Execute ',Title,' exit status=',Tool.ExitStatus,' ExitCode=',Tool.ExitCode]);
|
DebuglnThreadLog(['TExternalToolThread.Execute ',Title,' exit status=',Tool.ExitStatus,' ExitCode=',Tool.ExitCode]);
|
||||||
|
Loading…
Reference in New Issue
Block a user