mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-09 11:09:14 +02:00
* fix DosExitCode for sessions of other types, consider ExecFlags for other session types
git-svn-id: trunk@19398 -
This commit is contained in:
parent
9edae25cae
commit
af03a73af2
117
rtl/os2/dos.pas
117
rtl/os2/dos.pas
@ -54,6 +54,14 @@ Type
|
|||||||
threadvar
|
threadvar
|
||||||
(* For compatibility with VP/2, used for runflags in Exec procedure. *)
|
(* For compatibility with VP/2, used for runflags in Exec procedure. *)
|
||||||
ExecFlags: cardinal;
|
ExecFlags: cardinal;
|
||||||
|
(* Note that the TP/BP compatible method for retrieval of exit codes *)
|
||||||
|
(* is limited to only one (the last) execution! Including the following *)
|
||||||
|
(* two variables in the interface part allows querying the status of *)
|
||||||
|
(* of asynchronously started programs using DosWaitChild with dtNoWait *)
|
||||||
|
(* parameter, i.e. without waiting for the final program result (as *)
|
||||||
|
(* opposed to calling DosExitCode which would wait for the exit code). *)
|
||||||
|
LastExecRes: TResultCodes;
|
||||||
|
LastExecFlags: cardinal;
|
||||||
|
|
||||||
{$i dosh.inc}
|
{$i dosh.inc}
|
||||||
|
|
||||||
@ -64,12 +72,15 @@ function GetEnvPChar (EnvVar: string): PChar;
|
|||||||
function DosErrorModuleName: string;
|
function DosErrorModuleName: string;
|
||||||
(* In case of an error in Dos.Exec returns the name of the module *)
|
(* In case of an error in Dos.Exec returns the name of the module *)
|
||||||
(* causing the problem - e.g. name of a missing or corrupted DLL. *)
|
(* causing the problem - e.g. name of a missing or corrupted DLL. *)
|
||||||
|
(* It may also contain a queue name in case of a failed attempt *)
|
||||||
|
(* to create queue for reading results of started sessions. *)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
{$DEFINE HAS_GETMSCOUNT}
|
{$DEFINE HAS_GETMSCOUNT}
|
||||||
|
{$DEFINE HAS_DOSEXITCODE}
|
||||||
|
|
||||||
{$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
|
{$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
|
||||||
{$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
|
{$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
|
||||||
@ -79,7 +90,6 @@ implementation
|
|||||||
|
|
||||||
threadvar
|
threadvar
|
||||||
LastDosErrorModuleName: string;
|
LastDosErrorModuleName: string;
|
||||||
ExecCounter: cardinal;
|
|
||||||
|
|
||||||
|
|
||||||
const FindResvdMask = $00003737; {Allowed bits in attribute
|
const FindResvdMask = $00003737; {Allowed bits in attribute
|
||||||
@ -142,13 +152,40 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function DosExitCode: word;
|
||||||
|
var
|
||||||
|
Res: TResultCodes;
|
||||||
|
PPID: cardinal;
|
||||||
|
RC: cardinal;
|
||||||
|
begin
|
||||||
|
if (LastExecFlags = deAsyncResult) or (LastExecFlags = deAsyncResultDb) then
|
||||||
|
begin
|
||||||
|
RC := DosWaitChild (DCWA_PROCESS, dtWait, Res, PPID, LastExecRes.PID);
|
||||||
|
if RC = 0 then
|
||||||
|
(* If we succeeded, the process is finished - possible future querying
|
||||||
|
of DosExitCode shall return the result immediately as with synchronous
|
||||||
|
execution. *)
|
||||||
|
begin
|
||||||
|
LastExecFlags := deSync;
|
||||||
|
LastExecRes := Res;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
LastExecRes.ExitCode := RC shl 16;
|
||||||
|
end;
|
||||||
|
if LastExecRes.ExitCode > high (word) then
|
||||||
|
DosExitCode := high (word)
|
||||||
|
else
|
||||||
|
DosExitCode := LastExecRes.ExitCode and $FFFF;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure Exec (const Path: PathStr; const ComLine: ComStr);
|
procedure Exec (const Path: PathStr; const ComLine: ComStr);
|
||||||
{Execute a program.}
|
{Execute a program.}
|
||||||
var
|
var
|
||||||
Args0, Args: PByteArray;
|
Args0, Args: PByteArray;
|
||||||
ArgSize: word;
|
ArgSize: word;
|
||||||
Res: TResultCodes;
|
|
||||||
ObjName: string;
|
ObjName: string;
|
||||||
|
Res: TResultCodes;
|
||||||
RC: cardinal;
|
RC: cardinal;
|
||||||
ExecAppType: cardinal;
|
ExecAppType: cardinal;
|
||||||
HQ: THandle;
|
HQ: THandle;
|
||||||
@ -186,7 +223,7 @@ begin
|
|||||||
GetMem (Args0, MaxArgsSize);
|
GetMem (Args0, MaxArgsSize);
|
||||||
Args := Args0;
|
Args := Args0;
|
||||||
(* Work around a bug in OS/2 - argument to DosExecPgm *)
|
(* Work around a bug in OS/2 - argument to DosExecPgm *)
|
||||||
(* should not cross 64K boundary. *)
|
(* should not cross a 64K boundary. *)
|
||||||
if ((PtrUInt (Args) + 1024) and $FFFF) < 1024 then
|
if ((PtrUInt (Args) + 1024) and $FFFF) < 1024 then
|
||||||
Inc (pointer (Args), 1024);
|
Inc (pointer (Args), 1024);
|
||||||
ArgSize := 0;
|
ArgSize := 0;
|
||||||
@ -211,7 +248,8 @@ begin
|
|||||||
RC := DosExecPgm (ObjName, cardinal (ExecFlags), Args, nil, Res, Path);
|
RC := DosExecPgm (ObjName, cardinal (ExecFlags), Args, nil, Res, Path);
|
||||||
if RC = 0 then
|
if RC = 0 then
|
||||||
begin
|
begin
|
||||||
LastDosExitCode := Res.ExitCode;
|
LastExecFlags := ExecFlags;
|
||||||
|
LastExecRes := Res;
|
||||||
LastDosErrorModuleName := '';
|
LastDosErrorModuleName := '';
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -222,9 +260,49 @@ begin
|
|||||||
DSS := true;
|
DSS := true;
|
||||||
if DSS then
|
if DSS then
|
||||||
begin
|
begin
|
||||||
|
Str (GetProcessID, SPID);
|
||||||
|
Str (ThreadID, STID);
|
||||||
|
QName := '\QUEUES\FPC_Dos_Exec_p' + SPID + 't' + STID + '.QUE'#0;
|
||||||
FillChar (SD, SizeOf (SD), 0);
|
FillChar (SD, SizeOf (SD), 0);
|
||||||
SD.Length := SizeOf (SD);
|
SD.Length := SizeOf (SD);
|
||||||
|
RC := 0;
|
||||||
|
case ExecFlags of
|
||||||
|
deSync:
|
||||||
|
begin
|
||||||
SD.Related := ssf_Related_Child;
|
SD.Related := ssf_Related_Child;
|
||||||
|
LastExecFlags := ExecFlags;
|
||||||
|
SD.TermQ := @QName [1];
|
||||||
|
RC := DosCreateQueue (HQ, quFIFO or quConvert_Address, @QName [1]);
|
||||||
|
end;
|
||||||
|
deAsync,
|
||||||
|
deAsyncResult:
|
||||||
|
begin
|
||||||
|
(* Current implementation of DosExitCode does not support retrieval *)
|
||||||
|
(* of result codes for other session types started asynchronously. *)
|
||||||
|
LastExecFlags := deAsync;
|
||||||
|
SD.Related := ssf_Related_Independent;
|
||||||
|
end;
|
||||||
|
deBackground:
|
||||||
|
begin
|
||||||
|
(* Current implementation of DosExitCode does not support retrieval *)
|
||||||
|
(* of result codes for other session types started asynchronously. *)
|
||||||
|
LastExecFlags := ExecFlags;
|
||||||
|
SD.Related := ssf_Related_Independent;
|
||||||
|
SD.FgBg := ssf_FgBg_Back;
|
||||||
|
end;
|
||||||
|
deAsyncResultDB:
|
||||||
|
begin
|
||||||
|
(* Current implementation of DosExitCode does not support retrieval *)
|
||||||
|
(* of result codes for other session types started asynchronously. *)
|
||||||
|
LastExecFlags := ExecFlags;
|
||||||
|
SD.Related := ssf_Related_Child;
|
||||||
|
SD.TraceOpt := ssf_TraceOpt_Trace;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if RC <> 0 then
|
||||||
|
ObjName := Copy (QName, 1, Pred (Length (QName)))
|
||||||
|
else
|
||||||
|
begin
|
||||||
if Args = nil then
|
if Args = nil then
|
||||||
(* No parameters passed, Args not allocated for DosExecPgm, so allocate now. *)
|
(* No parameters passed, Args not allocated for DosExecPgm, so allocate now. *)
|
||||||
begin
|
begin
|
||||||
@ -237,40 +315,35 @@ begin
|
|||||||
SD.PgmInputs := PChar (@Args^ [Length (QName) + 1]);
|
SD.PgmInputs := PChar (@Args^ [Length (QName) + 1]);
|
||||||
SD.PgmName := PChar (Args);
|
SD.PgmName := PChar (Args);
|
||||||
SD.InheritOpt := ssf_InhertOpt_Parent;
|
SD.InheritOpt := ssf_InhertOpt_Parent;
|
||||||
Str (GetProcessID, SPID);
|
|
||||||
Str (ThreadID, STID);
|
|
||||||
Str (ExecCounter, SCtr);
|
|
||||||
Inc (ExecCounter);
|
|
||||||
QName := '\QUEUES\FPC_Dos_Exec_p' + SPID + 't' + STID + '.QUE'#0;
|
|
||||||
SD.TermQ := @QName [1];
|
|
||||||
SD.ObjectBuffer := @ObjName [1];
|
SD.ObjectBuffer := @ObjName [1];
|
||||||
SD.ObjectBuffLen := SizeOf (ObjName) - 1;
|
SD.ObjectBuffLen := SizeOf (ObjName) - 1;
|
||||||
RC := DosCreateQueue (HQ, quFIFO or quConvert_Address, @QName [1]);
|
|
||||||
if RC <> 0 then
|
|
||||||
ObjName := Copy (QName, 1, Pred (Length (QName)))
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
RC := DosStartSession (SD, SID, PID);
|
RC := DosStartSession (SD, SID, PID);
|
||||||
if (RC = 0) or (RC = 457) then
|
if (RC = 0) or (RC = 457) then
|
||||||
begin
|
begin
|
||||||
RC := DosReadQueue (HQ, RD, CISize, PCI, 0, 0, Prio, 0);
|
LastExecRes.PID := PID;
|
||||||
if RC = 0 then
|
if ExecFlags = deSync then
|
||||||
begin
|
begin
|
||||||
LastDosExitCode := PCI^.Return;
|
RC := DosReadQueue (HQ, RD, CISize, PCI, 0, 0, Prio, 0);
|
||||||
|
if (RC = 0) and (PCI^.SessionID = SID) then
|
||||||
|
begin
|
||||||
|
LastExecRes.ExitCode := PCI^.Return;
|
||||||
DosCloseQueue (HQ);
|
DosCloseQueue (HQ);
|
||||||
DosFreeMem (PCI);
|
DosFreeMem (PCI);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
DosCloseQueue (HQ);
|
DosCloseQueue (HQ);
|
||||||
|
end;
|
||||||
end
|
end
|
||||||
else
|
else if ExecFlags = deSync then
|
||||||
DosCloseQueue (HQ);
|
DosCloseQueue (HQ);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
if RC <> 0 then
|
if RC <> 0 then
|
||||||
begin
|
begin
|
||||||
LastDosErrorModuleName := ObjName;
|
LastDosErrorModuleName := ObjName;
|
||||||
LastDosExitCode := 0; (* Needed for TP/BP compatibility *)
|
LastExecFlags := deSync;
|
||||||
|
LastExecRes.ExitCode := 0; (* Needed for TP/BP compatibility *)
|
||||||
|
LastExecRes.TerminateReason := $FFFFFFFF;
|
||||||
end;
|
end;
|
||||||
DosError := RC;
|
DosError := RC;
|
||||||
if Args0 <> nil then
|
if Args0 <> nil then
|
||||||
@ -561,8 +634,8 @@ begin
|
|||||||
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
LastDosExitCode := 0;
|
FillChar (LastExecRes, SizeOf (LastExecRes), 0);
|
||||||
LastDosErrorModuleName := '';
|
LastDosErrorModuleName := '';
|
||||||
ExecFlags := 0;
|
ExecFlags := 0;
|
||||||
ExecCounter := 0;
|
LastExecFlags := deSync;
|
||||||
end.
|
end.
|
||||||
|
Loading…
Reference in New Issue
Block a user